衔接:这里主要是针对从零开始学java系列第一季第五期:运算符和表达式中递增递减运算中的一个常量的赋值说明
1、java中常量的赋值问题
在java中,我们知道,一个整数默认为int类型,由此呢?我们引发出了一个问题?
byte类型为什么赋值一个整数不会报错
下面我们来看一个例子:
同为byte类型的b1和b2的和却无法赋值给b3
b5如果赋值一个整数不会报错,但加上一个byte类型的数却会报错
对于b5,你可能还能解释:15默认为int类型,b1是byte类型,一个低级类型和一个高级类型进行运算,低级类型会自动向高级类型转换,那么b1+15的结果实际上是一个int类型的,那么也就无法赋值给byte类型的b5了
那么,对于b3的同类型无法赋值和一个整数常量,明明默认是int类型,为什么却可以赋值给byte类型?
针对上面的问题,我们先来看看b3处的报错信息:
-
它给我们的提示信息是类型错误,也就是说两个byte类型的数据相加之后的结果竟然变成了int类型;
-
要了解清楚这个问题的原因,必须要从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虚拟机指令集所支持的数据类型相关的内容)
-
通俗来说:就是在java虚拟机中有一个字节码指令,这些指令中的操作码可以用来为某一种数据类型服务,但这些操作码只有一个字节的长度,当一个数据类型支持多个数据类型相关的指令的时候,那么一个字节肯定是不够用的,比如一个常量10,它即支持int,还支持byte、short。,这时候就会将它们扩展为相应的int类型,所以呢,byte+byte实际上结果为int类型!
-
还有一种通俗的说法就是两个byte很容易超出byte所能存储的最大范围127,所以呢java虚拟机为其进行了数据类型转换。
-
另外呢,对于为什么byte能赋值常量整数这个问题,我这里借鉴一下其他的文章
首先,整数类型默认是int。这个毫无疑问。 其次,在允许的类型范围内,在此处byte:-128~127 而整数int 1 在这个范围,编译器会对常量自动进行向下的转化。 如果超出这个范围的常量,编译器直接报错。
-
还有一点需要提的就是,对于递增递减运算符来说,比如
byte b = 0;b++;
对于这里的b++来说,JVM会自动帮我们对b+1的结果进行一个强制转换,byte类型也是可以使用递增递减运算符的
引用资料:https://www.it1352.com/708803.html