我有一个相当简单但让我困惑的问题。假设字节变量a,b,c:
byte a = 5;
byte b = 3;
byte c = a + b; // wont compile
第3行不能编译,因为-我想- Java必须在后台进行计算,计算的结果是一个整数。如果没有显式转换,整数不能传递给字节。所以应该提供(byte)(a+b)但现在假设有第4行代码显式转换为整数…
c = (int) 8 ; // compiles
它编译,尽管字节变量'c'被显式转换为整数。Java是如何处理这方面的……?
您没有看到的是a+b
是运行时操作,而byte b = (int)8;
是编译时操作。因此,在编译时,编译器知道常数8
可以装入一个字节。因此,对(int)
的显式转换忽略。不管有没有(int)
,字节码都没有区别。
现在,在第一种情况下,如果两个字节变量都是final
(即常量),那么编译器将允许这样做:
public static void main(String[] args) {
final byte a = 5; // constant
final byte b = 3; // constant
byte c = a + b; // WILL compile;
}
第3行不能编译,因为-我想- Java必须在后台进行计算,计算的结果是一个整数。
正确的。
但现在假设有第四行代码显式转换为整数
c = (int) 8 ; // compiles
尽管字节变量'c'被显式转换为整数,但它仍可以编译。
因为您使用了文字值8
,而编译器知道8
适合byte
。
一个更好的比较是:
c = (int)b;
…失败。
关键是byte是8位,int是32位整型值。因此,例如,当你在127下添加两个字节数时,那么它可以添加到超过127的结果,这超出了字节范围,并且默认情况下Java对几乎所有数字都使用int。
JVM文档说:
编译器使用Java虚拟机指令在编译时或运行时将字节和短类型的文字值进行编码,这些指令将这些值符号扩展为int类型的值。布尔类型和char类型的文字值的加载是使用在编译时或运行时将文字零扩展为int类型的指令进行编码的。[…]。因此,对布尔型、字节型、char型和short型实际类型的值进行的大多数操作,都可以由对计算型int型值进行操作的指令正确执行。