猿问

变化的行为可能会降低精度

在Java中,当您执行


int b = 0;

b = b + 1.0;

您可能会损失精度误差。但是为什么要这么做


int b = 0;

b += 1.0;

没有任何错误吗?


FFIVE
浏览 317回答 1
1回答

RISEBY

那是因为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复合赋值)。
随时随地看视频慕课网APP

相关分类

Java
我要回答