这是Java语言规范方面的解释。
关于整数文字的部分(JLS 3.10.1)说:
int 类型的最大十进制文字是2147483648
(2 31 )。0
从to的所有十进制文字2147483647
可能出现在任何可能出现 int 文字的地方,但文字2147483648
可能仅作为一元否定运算符的操作数出现-
。
所以 ...
第一条语句是一个合法整数文字值的赋值。没有编译错误。
第二条语句是编译错误,因为2147483648
前面没有一元否定运算符。
第三条语句不包含超出范围的整数文字,因此从这个角度来看,它不是编译错误。
相反,第三条语句是JLS 15.18.2中描述的二进制加法表达式。这说明了有关整数情况的以下内容:
如果整数加法溢出,则结果是数学和的低位,以一些足够大的二进制补码格式表示。如果发生溢出,则结果的符号与两个操作数值的数学和的符号不同。
因此,2147483647 + 1
溢出并环绕到-2147483648
.
@Peter Lawrey 建议(轻率地?)第三条语句可以“由编译器重写”为+2147483648
,从而导致编译错误。
这是不正确的。
JLS 中没有任何内容表明常量表达式可以与非常量表达式具有不同的含义。相反,在1 / 0
JLS 之类的情况下,会翻转并说表达式不是常量表达式,因为它异常终止。(在JLS 15.28中)
JLS 非常努力地避免某些 Java 构造意味着不同事物的情况,具体取决于编译器。例如,它对“明确赋值”规则非常讲究,以避免只有智能编译器才能推断出变量总是在使用之前被初始化的情况。从代码可移植性的角度来看,这是一件好事。
The only significant area where there is "wiggle room" for compiler implementers to do platform specific things is in the areas of concurrency and the Java memory model. And there is a sound pragmatic reason for that - to allow multi-threaded Java applications to run fast on multi-core / multi-processor hardware.