平常我们所说的没区别,应该是这样的:
但是换别的写法,比如把b的类型变一下:
b提升了类型之后,会发现a= a+ b
是没办法编译通过的,需要强制类型转换。但是a+= b
却可以。反编译一下这个class文件:
在这种a比b类型范围要小的情况下。a= a+ b
需要强制类型转换,也就是我们常写的a= (int)(a+ b)
,而我们的a+= b
被我们的编译器在编译期做了一些小手脚。也就是编译器帮我们进行了强制类型转化。
那么,强制类型转换会带来什么问题呢?
强制类型转化,一般会带来精度丢失的问题。这里float的范围太大,用byte和short来演示,强制类型带来的问题:
可以知道输出结果是-128
。
基本类型在堆中所占的字节如下表:
我们常说的基本类型是存放在栈中的,这种说法并不全面。存放在堆中还是在栈中,是取决于这个变量声明的位置。如果是局部变量,则会存放在栈帧中。但是如果是成员变量(全局变量),那么就会存放在堆中。此外存放在栈中,基本类型所占的字节是固定的: 如果是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
。