Java中的原始转换和分配
我明白为什么以下是错误的:
byte a = 3; byte b = 8; byte c = a + b; // compile error
它不会编译。 expression式总是导致int
。 所以我们应该做一下明确的演员:
byte c = (byte) (a + b); // valid code
但我不明白为什么以下是正确的 :
byte d = 3 + 8; // it's valid! why?
因为文字整数(如3或8)总是隐含的int
。 而int-or-smaller
expression式总是会导致int
。 有人可以解释这里发生了什么吗?
我唯一能猜到的是编译器将这个expression式等同于下面的内容:
byte d = 11;
并不认为这是一个expression。
在编译时, 3 + 8
是否被评估为11
,这与编译器明确允许在某些情况下隐含地将int
缩小到byte
s有关。 特别是,语言规范明确允许隐式缩小转换为types为int
的常量expression式的byte
,它可以在编译时适合一个byte
。
JLS的相关部分是§5.2:
另外,如果expression式是
byte
,short
,char
或int
types的常量expression式(第15.28节):
- 如果variables的types是
byte
,short
或char
, 并且常量expression式的值可以用variables的types表示,则可以使用缩小的原始转换。编译时缩小的常量意味着代码如:
byte theAnswer = 42;
被允许。 如果没有缩小,那么整数文字42
types为int
的事实将意味着需要强制转换为byte
:
†:显然,按照规范,常量expression式需要进行评估,看它是否适合更窄的types。 但是要指出的是,如果没有这部分规范,编译器将不被允许进行隐式缩小转换 。
让我们在这里明确:
byte a = 3; byte b = 8;
这些被允许的原因是由于上面的规范部分。 也就是说,允许编译器将文字3
的隐式缩小转换为一个byte
。 这不是因为编译器在编译时将常量expression式3
为值3
。
我唯一能猜到的是编译器将这个expression式等同于下面的内容:
是的,它确实。 只要右边的expression式是由常量组成的 (这符合所需的基本types – 请参阅@Jason对JLS所说的完全相同的答案),您可以这样做。 这将不会编译,因为128超出范围:
byte a = 128;
请注意,如果你像这样转换你的第一个代码片段:
final byte a = 3; final byte b = 8; byte c = a + b;
它编译! 由于你的两个字节是final
,它们的expression式是常量,所以这次编译器可以确定当第一次初始化时,结果将适合一个字节。
但是,这不会编译:
final byte a = 127; // Byte.MAX_VALUE final byte b = 1; byte c = a + b // Nope...
编译器会错误地输出一个“可能的精度损失”。
这是因为3
和8
是编译时间常量。
因此,在编译时,编译器可以确定3 + 8
可以放入一个byte
variables中。
如果你把你的a
和b
变成final(常量)variables。 a + b
将成为编译时间常量。 所以编译没有任何问题。
final byte a = 3; final byte b = 8; byte c = a + b;