Fork me on GitHub

a和b相加

a= a+ ba+= b。这两者有什么区别?

平常我们所说的没区别,应该是这样的:

1
2
3
4
int a= 1;
int b= 2;
a= a+ b;
a+= b;

但是换别的写法,比如把b的类型变一下:

1
float b= 2F;

1
        b提升了类型之后,会发现a= a+ b是没办法编译通过的,需要强制类型转换。但是a+= b却可以。反编译一下这个class文件:

1
2
3
4
5
6
7
8
9
10
11
public void fun(){
int a= 1;
float b= 2F;
a+= b;
}
//反编译class的内容
public void fun(){
byte var1= 1;
float var2= 2.0F;
int var10000= (int)((float)var1+ var2);
}

        在这种a比b类型范围要小的情况下。a= a+ b需要强制类型转换,也就是我们常写的a= (int)(a+ b),而我们的a+= b被我们的编译器在编译期做了一些小手脚。也就是编译器帮我们进行了强制类型转化。
        那么,强制类型转换会带来什么问题呢?
2
        强制类型转化,一般会带来精度丢失的问题。这里float的范围太大,用byte和short来演示,强制类型带来的问题:

1
2
3
4
5
6
public void fun(){
byte a= 1;
short b= 127;
a= (byte)(a+ b);
System.out.println(a);
}

        可以知道输出结果是-128
        基本类型在堆中所占的字节如下表:
3
        我们常说的基本类型是存放在栈中的,这种说法并不全面。存放在堆中还是在栈中,是取决于这个变量声明的位置。如果是局部变量,则会存放在栈帧中。但是如果是成员变量(全局变量),那么就会存放在堆中。此外存放在栈中,基本类型所占的字节是固定的: 如果是32位计算机那么就是4字节; 64位便是8字节。
由上图可知byte占1字节,也就是8位,如果每一位都为1(11111111),那么理论上就是它所能表示的最大内容。
        但最大并不是255!
        因为正负的原因,计算机中使用补码的形式表示二进制,高1位表示符号位(0为正,1为负)。因此对于8位来说,最大只能是01111111,也就是127(0表示它为正)。
        刚才那个计算,不考虑类型转换,那么a+ b等于128。并且对于所占2字节的short来说那就是0000000010000000。但是我们强制类型转化成了byte,这时做了一件事情,那就是高1字节的内容全部砍掉,也就是只剩下了10000000
按照刚才所说的,高1位的内容表示正负。1为负,但结果并不是0!
        对于含有补码形式的10000000,我们要用补码的方式去计算。计算的套路如下: 高1位为1,那么这个数就是负数。想要知道是负几,我们需要将10000000按位取反,也就是01111111。还没完,此时还要再加1,也就是10000000。现在得到的这个数是几,那么就是负几,10000000是十进制的128,因此补码形式的10000000也就是-128

Your support will encourage me to continue to create!