Java 可能导致精度损失的变化行为

Java 可能导致精度损失的变化行为,java,implicit-conversion,compound-assignment,Java,Implicit Conversion,Compound Assignment,在Java中,当您 int b = 0; b = b + 1.0; 可能会出现精度损失错误。但如果你这么做了,为什么会这样 int b = 0; b += 1.0; 没有任何错误?那是因为b+=1.0相当于b=(int)((b)+(1.0))。在复合赋值操作中隐藏 (JLS第三版): 形式为E1 op=E2的复合赋值表达式等价于E1=(T)((E1)op(E2)),其中T是E1的类型,但E1仅计算一次 例如,以下代码是正确的: short x = 3; x += 4.6; 并导致x具有值7

在Java中,当您

int b = 0;
b = b + 1.0;
可能会出现精度损失错误。但如果你这么做了,为什么会这样

int b = 0;
b += 1.0;

没有任何错误?

那是因为
b+=1.0
相当于
b=(int)((b)+(1.0))。在复合赋值操作中隐藏

(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!

值得注意的是,隐含的复合赋值是这本好书中的难题9:Tweedledum的主题。以下是本书的一些摘录(为简洁起见略加编辑):

许多程序员认为
x+=i
只是
x=x+i的简写。事实并非如此:如果结果的类型比变量的类型宽,则复合赋值运算符将执行静默缩小原语转换

为了避免令人不快的意外情况,不要对类型为
字节
字符
的变量使用复合赋值运算符。在
int
类型的变量上使用复合赋值运算符时,请确保右侧的表达式不是
long
float
double
类型。对类型为
float
的变量使用复合赋值运算符时,请确保右侧的表达式不是类型为
double
。这些规则足以防止编译器生成危险的狭窄强制转换

对于语言设计者来说,复合赋值运算符生成不可见的强制转换可能是一个错误;如果变量的类型比计算结果的类型窄,则复合赋值可能是非法的


最后一段值得注意:C在这方面要严格得多(参见)。

谢谢。如果要使用的关键字类似于“+=”,则很难搜索文档:PAll
op=
运算符在Java中称为“复合赋值”。但是,是的,我确实认为在大多数搜索引擎中,查询符号而不是关键词是很困难的。这里有谷歌人吗?我想要一个搜索框,其中也考虑到像+=<和>:)是的,我希望有一种方法可以像谷歌代码搜索一样使用正则表达式。但话说回来,他们需要改变他们的整个索引系统。我刚刚被这种行为弄明白了,我想知道为什么Java设计师添加了这种隐式转换?这样做有什么好处?主动添加没有好处的额外行为似乎太奇怪了……可能,只是可能是因为在前者中,它将b转换为浮点,然后添加,然后将其转换回整数?后者可能是将1.0转换成整数,然后进行整数加法?不过只是猜测而已。