为什么 Java 中的复合赋值不能捕获溢出问题?
令我震惊的是,事实证明以下代码将在没有警告的情况下进行编译:
public void test()
{
int value = 2000000000;
long increment = 1000000000;
value += increment;
}
然而,正如您所料,这会产生编译时错误:
public void test()
{
int value = 2000000000;
long increment = 1000000000;
value = value + increment;
}
我检查了它,事实上,JLS(第 15.26.2 节)有这样的说法:
E1 op = E2 形式的复合赋值表达式相当于 E1 = (T) ((E1) op (E2)),其中 T 是 E1 的类型,但对 E1 进行求值 仅一次。
这对我来说似乎很荒谬。为什么他们觉得有必要在这里明确选角?看来自动类型转换无论如何都会处理加宽,并且像这样的自动缩小几乎肯定会导致整数溢出。
To my shock, it turns out that the following code will compile without even warnings:
public void test()
{
int value = 2000000000;
long increment = 1000000000;
value += increment;
}
Whereas this gives a compile-time error, as you would expect:
public void test()
{
int value = 2000000000;
long increment = 1000000000;
value = value + increment;
}
I checked it up and indeed, the JLS (section 15.26.2) has this to say:
A compound assignment expression of the form E1 op = E2 is equivalent to
E1 = (T) ((E1) op (E2)), where T is the type of E1, except that E1 is evaluated
only once.
This seems ridiculous to me. Why did they feel the need to explicitly cast here? It seems that automatic type conversion would have handled the widening anyway, and automatically narrowing like this is pretty much guaranteed to result in integer overflow.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这里是一种解释:
Here is one explanation:
复合赋值运算符由 JLS 指定 (15.26 .2)如下:
在本例中,E1 的类型为
int
E2 的类型为long
>,而 op 是+
所以这相当于:int
和long
相加得到一个long
。然后在赋值之前将其强制转换为int
,这一切都很好,因此不会出现编译错误。 /code>),这个简单的赋值没有类型转换
,那么为什么他们这样定义它?
我认为原因是让这样的例子有效:
没有类型转换,
b += 1
将是一个编译错误,您需要将其编写为:The compound assignment operators are specified by the JLS (15.26.2) as follows:
In this case E1 is of type
int
E2 is of typelong
, and op is+
. So this is equivalent to:The addition of an
int
and along
gives along
that is then cast back to anint
before assignment. That is all fine, hence no compilation error.The difference between this and the simple assignment (i.e.
value = value + increment;
), is that the simple assignment doesn't have a typecast.OK, so why did they define it this way?
I think that the reason is to make examples like this work:
Without the typecast,
b += 1
would be a compilation error and you'd need to write it as:这个链接已经分析了你提出的问题。
不同的行为可能导致精度损失
This link has analyzed the problem you have brought up.
Varying behavior for possible loss of precision