1 回答
TA贡献1856条经验 获得超5个赞
那是因为b += 1.0;等价于b = (int) ((b) + (1.0));。的基本收缩转换(JLS 5.1.3)隐藏在复合赋值操作。
JLS 15.26.2复合赋值运算符(JLS第三版):
形式为E1 op = E2的复合赋值表达式等效于E1 =(T)(((E1)op(E2))),其中T是E1的类型,只是E1仅被评估一次。
例如,以下代码是正确的:
short x = 3;
x += 4.6;
并导致x具有该值,7因为它等效于:
short x = 3;
x = (short)(x + 4.6);
这也解释了为什么以下代码会编译:
byte b = 1;
int x = 5;
b += x; // compiles fine!
但这不是:
byte b = 1;
int x = 5;
b = b + x; // DOESN'T COMPILE!
在这种情况下,您需要显式转换:
byte b = 1;
int x = 5;
b = (byte) (b + x); // now it compiles fine!
值得注意的是,复合赋值中的隐式强制转换是精彩书籍Java Puzzlers中的Puzzle 9:Tweedledum的主题。这是本书的摘录(为简洁起见,对其进行了略作编辑):
许多程序员认为这x += i;仅仅是的简写x = x + i;。事实并非如此:如果结果的类型比变量的类型宽,则复合赋值运算符将执行无声收窄基元转换。
为了避免不愉快的意外,不要类型的变量使用复合赋值运算符 byte,short或char。当类型的变量使用复合赋值运算符int,确保在右手侧的表达式的类型不long,float或double。在类型变量上使用复合赋值运算符时float,请确保右侧的表达式不是type double。这些规则足以防止编译器生成危险的缩小强制类型转换。
对于语言设计师来说,复合赋值运算符生成不可见的强制转换可能是一个错误;变量类型比计算结果窄的复合赋值可能是非法的。
最后一段值得注意:C#在这方面要严格得多(请参见C#语言规范7.13.2复合赋值)。
添加回答
举报