为什么 Java 中的扩充赋值运算符会给出不同的结果?

Why does the augmented assignement operator in Java give a different result?

考虑以下代码:

class Converter {
    public static void main(String args[]) {
        byte num = 1;
        num = num * 2.5;
        System.out.println("Result is: " + num);
    }
}

编译器抛出以下错误:

error: incompatible types: possible lossy conversion from double to the byte at line 1

如果我更改 main() 方法的第二行并使用 *= shorthand 运算符:

class Converter {
    public static void main(String args[]) {
        byte num = 1;
        num *= 2.5;
        System.out.println("Result is: " + num);
    }
}

代码成功编译并运行并输出:

Result is: 2

为什么 *= shorthand 运算符的行为与完整表达式 num = num * 2.5 不同?

从 JLS compound assigment operator 文档中,您可以看到以下示例:

For example, the following code is correct:

short x = 3;
x += 4.6;

and results in x having the value 7 because it is equivalent to:

short x = 3;
x = (short)(x + 4.6);

它只是默认自动转换结果。

PS :在此 other answer 中,我试图解释您需要使用 JLS

进行如下操作的原因
short x = 3;
x = x + 1; //Won't compile

它真的很新,所以我愿意接受建议。

正如 AxelH 所说,它是 compound assignement 但我想强调一下:

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T) ((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

这意味着根据定义它正在转换结果。例如:

byte b = 1;
b *= 2.3;
System.out.println(b); // prints 2

来自您的评论:

So can I say that shorthand operator suppresses the lossy conversion error and simply does what input it has?

不,你不能。它没有抑制任何错误,因为在转换时没有错误(在这种情况下)。

根据 java 语言规范 "15.26.2. Compound Assignment Operators"

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

你可以在编译后看到你的例子的字节码(检查instruction 3-10)。

   3: i2d //convert an int into a double
   4: ldc2_w          #2                  // double 2.5d
   7: dmul //multiply two doubles
   8: d2i //    convert a double to an int
   9: i2b //convert an int into a byte
  10: istore_1 //store int value into variable 1