Home

Wisim

29 Oct 2016

Java中 a=a+b 和 a+=b 的区别

千万不要放过任何一个小的知识点(一个这么小的点也可以拿来写一篇文章 哈?)

首先网传 a+=b 的效率会比 a=a+b 的效率要高一点,但是我验证了一下,好像并没有这回事。运行 1000000000 次 a=a+1的时间和 a+=1的时间几乎差不多,而且有时候前者快,有时候后者快。这里就不讨论效率高低这个区别了。

说一下另外一个很显著的区别: += 这个运算中包含了强制转换的操作。所以当我们把两个不同类型的变量使用 += 操作的时候,其实编译器已经自动帮我们强制转型了。而 =+ 并没有自动转型,所以如果我们没有手动强制转型的话,编译的时候是会报错的。

看一下测试代码:

public class PlusEqual {
    static char a = 1;
    static int b = 3;
    public static void main(String[] args) {
        a += b;
        a = a + b;//(char)(a + b);
    }
}

现在我们编译的话,是会报错的:

错误: 不兼容的类型: 从int转换到char可能会有损失
        a = a + b;

因为此时a+b此时得到的结果是int,不能直接赋给 char 型的 a。需要强制转型成 a = (char)(a + b);

要记住两点:

一、运算过程中,低精度的类型向高精度类型转换。 二、如果将高精度的数值赋值给低精度类型变量,则必须要进行显性的强制转换。


课外阅读:关于小数浮点数精度的问题

你猜 System.out.println(0.1 * 3); 打印出来的结果是什么?对,是 0.30000000000000004。这就是我们要讨论的小数浮点数的精度问题,而整数浮点数没有精度这个问题。为啥子呢?

先说整数为啥没有这个问题,其实不管是小数还是整数,计算机都是使用二进制存储的。例如 3 用二进制可以表示为 11。因为 2^0 = 1, 2^1 = 2,就这两,我一个一个往上怼,就可以表示一切整数了,对吧,我就不证明了啊哈哈(不会)。

但是小数呢? 2^-1 = 0.5 , 2^-2 = 0.25。由于 double 的长度是64位,其中符号位S占1位,阶码e占11位,尾数M占52位。最终浮点数可以表达为:(-1)^S * M * 2(e)。这样能精确表达的出来的小数其实是有限的,比如 0.25可以直接表达成:(-1)^0 * 1.000000000000 * 2^(-2)。但是0.3这种小数呢?很显然是无法精确表达的,只能通过近似表达,精确到小数点后的16位。

这样也引申出了一个题目哟:3 * 0.1 == 0.3 将会返回什么?true 还是 false?


THE END.