为什么Java中的复合赋值没有捕获溢出问题?

Tre*_*kaz 13 java integer-overflow compound-assignment

令我震惊的是,以下代码将在没有警告的情况下编译:

public void test()
{
    int value = 2000000000;
    long increment = 1000000000;
    value += increment;
}
Run Code Online (Sandbox Code Playgroud)

虽然这会产生编译时错误,正如您所期望的那样:

public void test()
{
    int value = 2000000000;
    long increment = 1000000000;
    value = value + increment;
}
Run Code Online (Sandbox Code Playgroud)

我检查了一下,事实上,JLS(第15.26.2节)有这样的说法:

形式E1 op = E2的复合赋值表达式等效于E1 =(T)((E1)op(E2)),其中T是E1的类型,除了E1仅被评估一次.

这对我来说似乎很荒谬.为什么他们觉得有必要在这里明确投射?似乎自动类型转换无论如何都会处理扩展,并且像这样自动缩小几乎可以保证导致整数溢出.

Dav*_* L. 4

是一种解释:

当您进行分配(第一个代码片段)时,java 会强制执行类型检查,因为 LHS 和 RHS 很可能彼此独立。

但复合运算符更像是增量运算符。+= 修改所涉及变量的值,而不是为变量分配新值。当您修改一个字节时,您期望得到一个字节作为结果。为了让生活更轻松,java 对复合运算符进行了隐式类型转换,因为它们是修饰符。