我们都知道在Java中这些运算符:
a++;
++a;
a += 1;
a = a + 1;
做同样的事情,他们只是将1添加到变量'a'
然而,为什么这些陈述并非都是真的,这背后的原理是什么?
byte a = 1;
a++;
++a;
a += 1;
a = a + 1; // This line will result to a compile time error
为什么?
答案 0 :(得分:3)
每当您在两个不同类型的操作数之间执行二进制操作时,其中一个操作数将被提升为更高类型。然后操作的结果就是那种类型。
因此,在您的情况下,byte
类型a
首先会提升为int
,因为1
是int
类型。然后在加法运算之后,结果为int
类型。现在,由于您无法将int
分配给byte
,因此您需要进行类型转换以删除编译器错误:
byte a = 2;
a = a + 1; // Error: Cannot assign an int value to byte
a = (byte)(a + 1); // OK
<小时/> 现在,在复合赋值运算符的情况下,类型转换是为您隐式完成的。表达式:
a += 1
在内部转换为:
a = (byte)(a + 1);
这在JLS中指定 - §15.26.2 Compound Assignment Operator:
E1 op = E2形式的复合赋值表达式等效于E1 =(T)((E1)op(E2)),其中T是E1的类型,但E1仅被评估一次。
类似于前缀增量运算符和后缀增量运算符的情况。
根据JLS - §15.15 Unary Operators:
前缀增量表达式的类型是变量的类型。
答案 1 :(得分:0)
a = a + 1;
这是由于表达式a = a + 1;
的类型。 LHS被提升为int
,然后执行添加。然后,您尝试将int
值分配回byte
而不进行转换。
应用扩展基元转换(第5.1.2节)来转换以下规则指定的一个或两个操作数:
如果任一操作数的类型为double,则另一个操作数转换为double。
否则,如果任一操作数的类型为float,则另一个操作数转换为float。
否则,如果任一操作数的类型为long,则另一个操作数转换为long。
- 醇>
否则,两个操作数都将转换为int类型。
<强>一个++; ++一个; 强>
这里的类型是变量类型的类型。再次根据JLS 15.15
前缀增量表达式的类型是变量的类型。
前缀减量表达式的类型是变量的类型。
a + = 1;
E1 op = E2形式的复合赋值表达式等效于E1 =(T)((E1)op(E2)),其中T是E1的类型,但E1仅被评估一次。
因此,a += 1;
相当于a = (byte)(a+1);
,因为它是隐式完成的。