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

为什么Java中的增广赋值运算符会给出不同的结果?,java,operators,Java,Operators,考虑以下代码: 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 doubl

考虑以下代码:

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()
方法的第二行并使用
*=
速记运算符:

class Converter {
    public static void main(String args[]) {
        byte num = 1;
        num *= 2.5;
        System.out.println("Result is: " + num);
    }
}
代码编译成功并与输出一起运行:

Result is: 2
为什么
*=
速记运算符的行为不同于JLS文档中的完整表达式
num=num*2.5

,您可以看到以下示例:

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

结果x的值为7,因为它等于:

默认情况下,它只是自动转换结果

PS:在本文中,我试图解释您需要使用JLS强制执行以下操作的原因

short x = 3;
x = x + 1; //Won't compile

它确实是新的,所以我愿意接受这里的建议。

正如AxelH已经说过的,它是一个新的,但我想用uderline表示:

形式为
E1 op=E2
的复合赋值表达式是等效的 to
E1=(T)((E1)op(E2))
,其中
T
E1
的类型,除了
E1
仅评估一次

这意味着,根据定义,它正在铸造结果。例如:

byte b = 1;
b *= 2.3;
System.out.println(b); // prints 2
来自您的评论:

那么我可以说速记操作符抑制了有损转换吗 错误并简单地执行它的输入


不,你不能。它不会抑制任何错误,因为在强制转换(在此上下文中)中没有错误。

根据java语言规范

形式为E1 op=E2的复合赋值表达式是等效的 to E1=(T)((E1)op(E2)),其中T是E1的类型,但E1除外 仅评估一次

在编译之后,您可以看到示例的字节码(检查3-10)


为什么你认为这不会发生?它基本上执行
x=(字节)(x*y)
。所以它确实有一个隐式类型转换。我的意思是,第一个错误已经警告您,当从
double
转换为
byte
时,类型转换将使您失去预精度。请使用
javap-v Converter.class
查看第二种情况下发生了什么。请特别注意d2i和i2b指令:)那么我可以说速记操作符抑制有损转换错误,只做它的输入吗?不,你不能。你可以说@SomeJavaGuy所说的,实际上引用了JLS,复合赋值(不是“速记”)操作符包括一个cast,一个在非复合示例中省略的cast。@AxelH我认为你的答案是好的。我也投了赞成票。但我只是想强调为什么会发生这种情况。现在读到OP的评论让我更好地解释,它并没有抑制任何错误。相反,它是铸造。这是不同的。我同意,顺便说一下,您的示例应该使用
b=1
而不是
b=10
来显示有损转换;)
short x = 3;
x = x + 1; //Won't compile
byte b = 1;
b *= 2.3;
System.out.println(b); // prints 2
   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