我理解为什么以下是错误的:
byte a = 3;
byte b = 8;
byte c = a + b; // compile error
它不会编译。表达式始终会生成int
。所以我们应该做了明确的演员:
byte c = (byte) (a + b); // valid code
但是我不明白为什么以下是正确的:
byte d = 3 + 8; // it's valid! why?
因为字面整数(例如3或8)总是隐含int
。而且int-or-smaller
表达式也总是导致int
。谁能解释一下这里发生了什么?
我唯一可以猜到的是编译器将此表达式等同于以下内容:
byte d = 11;
并不认为这是一个表达。
答案 0 :(得分:46)
less†与3 + 8
是否在编译时评估为11
,更多与更多有关在某些情况下,明确允许编译器隐式地将int
缩小为byte
s。特别是,语言规范明确允许将byte
类型int
的常量表达式隐式缩小转换,以便在编译时适合byte
。
此外,如果表达式是类型
byte
,short
的常量表达式(第15.28节),char
或int
:
- 如果类型为,则可以使用缩小的基元转换 变量是
byte
,short
或char
,和常量的值 表达式可以在变量的类型中表示。编译时缩小常量意味着代码如下:
byte theAnswer = 42;
被允许。没有缩小,整数文字42
具有类型int
的事实 意味着需要投射到byte
:
†:显然,根据规范,需要评估常量表达式以确定它是否适合较窄的类型。 但重点是,如果没有规范的这一部分,编译器将不允许进行隐式缩小转换。
我们在这里说清楚:
byte a = 3;
byte b = 8;
允许这些的原因是由于规范的上述部分。也就是说,允许编译器将文字3
隐式缩小转换为byte
。这不是因为编译器在编译时将常量表达式3
计算为其值3
。
答案 1 :(得分:41)
我唯一可以猜到的是编译器将此表达式等同于以下内容:
是的。只要右侧表达式由常量(符合所需的基本类型 - 请参阅@Jason关于JLS对此的说明的答案),您就可以做到这一点。这将无法编译,因为128超出范围:
byte a = 128;
请注意,如果您将第一个代码段转换为:
final byte a = 3;
final byte b = 8;
byte c = a + b;
它编译!由于你的两个字节是final
和,它们的表达式是常量,这次,编译器可以确定结果在首次初始化时适合一个字节。
然而,这不会编译:
final byte a = 127; // Byte.MAX_VALUE
final byte b = 1;
byte c = a + b // Nope...
编译器会因“可能的精度损失”而出错。
答案 2 :(得分:0)
3
和8
是编译时常量。 因此,在编译时,编译器可以识别出3 + 8
可以放入byte
变量。
如果您将a
和b
设为最终(常量)变量。 a + b
将成为编译时常量。因此,它将编译没有任何问题。
final byte a = 3;
final byte b = 8;
byte c = a + b;