[英]Why doesn't Java have compound assignment versions of the conditional-and and conditional-or operators? (&&=, ||=)
[英]Why doesn't compound assignment in Java catch overflow problems?
令我震惊的是,以下代码将在没有警告的情况下编译:
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仅被评估一次。
这对我来说似乎很荒谬。 为什么他们觉得有必要在这里明确投射? 似乎自动类型转换无论如何都会处理扩展,并且像这样自动缩小几乎可以保证导致整数溢出。
这是一个解释:
当你执行一个赋值(第一个代码片段)时,java强制执行类型检查,因为LHS和RHS很可能彼此独立。
但复合运算符更像是增量运算符。 + =修改所涉及变量的值,而不是为变量赋值。 修改字节时,您希望得到一个字节作为结果。 为了简化生活,java为复合运算符执行隐式类型转换,因为它们是修饰符。
复合赋值运算符由JLS( 15.26.2 )指定如下:
“
E1 op= E2
形式的复合赋值表达式相当于
E1 = (T)((E1) op (E2))`,
其中T是E1的类型,但E1仅被评估一次。“
在这种情况下,E1的类型为int
E2的类型为long
,op为+
。 所以这相当于:
value = (int)(value + increment);
添加一个int
和一个long
会给出一个long
,然后在赋值之前将其int
转换为int
。 这一切都很好,因此没有编译错误。
这与简单赋值(即value = value + increment;
)之间的区别在于简单赋值没有类型转换。
好的, 为什么他们这样定义呢?
我认为原因是做这样的例子:
byte b = ...
b += 1;
如果没有类型转换, b += 1
将是编译错误,您需要将其写为:
b += (byte) 1;
此链接分析了您提出的问题。
为避免令人不快的意外,请不要对byte,short或char类型的变量使用复合赋值运算符。 在int类型的变量上使用复合赋值运算符时,请确保右侧的表达式不是long,float或double类型。 在float类型的变量上使用复合赋值运算符时,请确保右侧的表达式不是double类型。 这些规则足以防止编译器生成危险的缩小转换。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.