我们都知道在 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
为什么?
我们都知道在 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
为什么?
每当您在不同类型的两个操作数之间执行二元运算时,其中一个操作数将提升为更高类型。然后操作的结果就是那个类型。
因此,在您的情况下,该byte
类型a
首先被提升为 an int
,因为1
它是一种int
类型。然后经过加法运算,结果为int
. 现在,由于您无法将 a 分配int
给 a 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 复合赋值运算符中指定:
E1 op= E2 形式的复合赋值表达式等价于 E1 = (T) ((E1) op (E2)),其中 T 是 E1 的类型,除了 E1 只计算一次。
前缀增量运算符和后缀增量运算符的情况类似。
根据 JLS - §15.15 一元运算符:
前缀增量表达式的类型是变量的类型。
一 = 一 + 1;
这是由于表达式的类型a = a + 1;
。LHS 被提升到int
然后执行加法。然后,您尝试将int
值分配回 abyte
而不进行强制转换。
加宽原语转换(第 5.1.2 节)适用于转换以下规则指定的一个或两个操作数:
如果任一操作数是 double 类型,则另一个操作数将转换为 double。
否则,如果任一操作数的类型为浮点型,则另一个将转换为浮点型。
否则,如果任一操作数是 long 类型,则另一个将转换为 long。
否则,两个操作数都转换为 int 类型。
一个++;++一个;
这里的类型是变量的类型。再次按照JLS 15.15
前缀增量表达式的类型是变量的类型。
前缀减量表达式的类型是变量的类型。
一个+= 1;
E1 op= E2 形式的复合赋值表达式等价于 E1 = (T) ((E1) op (E2)),其中 T 是 E1 的类型,除了 E1 只计算一次。
因此这里a += 1;
等同于a = (byte)(a+1);
,因为它是隐式完成的。