不同的行为可能会导致精度下降

szu*_*pie 30 java implicit-cast compound-assignment

在Java中,当你这样做

int b = 0;
b = b + 1.0;
Run Code Online (Sandbox Code Playgroud)

您可能会丢失精度错误.但是,如果你这样做,为什么呢?

int b = 0;
b += 1.0;
Run Code Online (Sandbox Code Playgroud)

没有任何错误?

pol*_*nts 34

那是因为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)),其中TE1的类型,除了E1仅被评估一次.

例如,以下代码是正确的:

short x = 3;
x += 4.6;
Run Code Online (Sandbox Code Playgroud)

并导致x具有该值,7因为它相当于:

short x = 3;
x = (short)(x + 4.6);
Run Code Online (Sandbox Code Playgroud)

这也解释了为什么以下代码编译:

byte b = 1;
int x = 5;
b += x; // compiles fine!
Run Code Online (Sandbox Code Playgroud)

但这不是:

byte b = 1;
int x = 5;
b = b + x; // DOESN'T COMPILE!
Run Code Online (Sandbox Code Playgroud)

在这种情况下你需要显式地转换:

byte b = 1;
int x = 5;
b = (byte) (b + x); // now it compiles fine!
Run Code Online (Sandbox Code Playgroud)

值得注意的是,复合作业中的隐含演员是益智9:Tweedledum的主题,来自精彩的Java Puzzlers.以下是本书的一些摘录(为简洁起见略有编辑):

许多程序员认为这x += i;只是简写x = x + i;.这不是真的:如果结果的类型比变量的类型宽,则复合赋值运算符执行静默缩小基元转换.

为了避免不愉快的意外,不要类型的变量使用复合赋值运算符 byte,shortchar.当类型的变量使用复合赋值运算符int,确保在右手侧的表达式的类型不long,floatdouble.在类型变量上使用复合赋值运算符时float,请确保右侧的表达式不是类型double.这些规则足以防止编译器生成危险的缩小转换.

对于语言设计者来说,复合赋值运算符生成隐形强制转换可能是一个错误.复合赋值,其中变量的类型比计算结果的类型更窄应该是非法的.

最后一段值得注意:C#在这方面要严格得多(参见C#语言规范7.13.2复合赋值).

  • 谢谢.当您要使用的关键字类似于"+ ="时,很难搜索文档.:P (5认同)
  • 这里的任何谷歌?我想要一个搜索框,它也会考虑像+ =和<:)这样的符号 (2认同)