背景:
之前偶然看到有讨论这个问题,在网上搜了半天,结果都不尽如人意,解释没有到位,
有的说byte加byte默认就是int,那为什么这么做呢? 这不是找麻烦么?这种奇怪的默认还有哪些?带来一些列疑问。。。。。。
有的说byte存储的就是整型数据,这种说法的对错姑且不论,至少我觉得难免有点牵强了,还是疑问重重。。
所以今天专门总结一下:
----------------------------------------------------------------------------------------------------------------------------------------------------------------
一、问题:
先看这段代码:
(1) byte a=1;
(2) byte b=2;
(3) byte d=-1;
(4) byte c=128; //编译错误,因为byte类型的数据是单字节,表示十进制数的范围是-128~+127(第一位是符号位,代表正负数)
(5) a = a+b;//编译错误,byte+byte的结果不是byte类型,提示需要强制转换为byte类型或者把等式左边类型改编为int.
(6) a = (byte)(a+b);
(1)(2)(3)行,正常赋值操作,没有问题;
(4)行,编译错误,实际上是因为byte类型的数据是单字节,表示十进制数的范围是-128~+127;
(5)行,就是今天的重点了,也报了编译错误,byte+byte的结果不是byte类型,反而提示需要强制转换为byte类型或者把等式左边类型改编为int. 就如第(6)行那样。 这就像两个人站在一起,需要有人强制解释一下,别人才知道这是两个人,而不是其他的什么东西,这也太奇怪了!
二、对背后原因的探索:
要了解清楚这个问题的原因,必须要从Java虚拟机的指令集说起,每种指令代表了一种操作。
首先要说明的是:在Java虚拟机中,对于大部分与数据类型相关的字节码指令,他们的操作码助记符中都有特殊的字符来表示专门为哪种数据类型服务。
但是Java虚拟机的操作码长度只有一个字节,这就带来一个问题,如果每种与数据类型相关的指令都支持Java虚拟机运行时数据类型的话,显然一个字节就不够用了。 所以Java虚拟机规范中,这种特性"Not Orthogonal",并非每种数据类型和每一种操作都有对应的指令。
大部分的指令都没有支持byte、char、short,没有任何指令支持boolean类型。编译器在编译期或者运行期将byte和short类型的数据带符号扩展为相应的int类型数据,将boolean和char类型数据零位扩展为相应的int类型数据。与之类似的,在处理byte、char、short和boolean类型的数组时,也会转换成对应的int类型的字节码指令来处理。因此,大多数对于byte、char、short和boolean类型数据的操作,实际上都是使用相应的int类型作为运算类型的。
参考书籍:《深入理解Java虚拟机:JVM高级特性与最佳实践》(第三部分,第6章,6.4.1小节:P197-P199 关于Java虚拟机指令集所支持的数据类型相关的内容)