字节一元运算



我们都知道在Java中这些运算符:

a++;
++a;
a += 1;
a = a + 1;

做同样的事情,他们只是在变量"a"上加1

然而,为什么这些说法并不都是真的,这背后的原则是什么?

byte a = 1;
a++;
++a;
a += 1;
a = a + 1; // This line will result to a compile time error

为什么?

无论何时在不同类型的两个操作数之间执行二进制运算,其中一个操作数都会升级为更高的类型。然后运算的结果就是这种类型的。

因此,在您的案例中,byte类型a首先被提升为int,因为1int类型。然后在加法运算之后,结果是类型为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复合分配运算符:中有规定

形式E1-op=E2的复合赋值表达式等价于E1=(T)((E1)-op(E2)),其中T是E1的类型,不同之处在于E1仅被评估一次。

前缀增量运算符后缀增量运算符的情况类似
根据JLS-§15.15一元算子:

前缀增量表达式的类型就是变量的类型。

a=a+1

这是由于表达式a = a + 1;的类型。LHS被提升为CCD_ 10,然后进行加法运算。然后,您将尝试在不强制转换的情况下将int值分配回byte

参考JLS 5.6.2

加宽基元转换(§5.1.2)适用于根据以下规则转换一个或两个操作数:

  1. 如果任一操作数的类型为double,则另一个操作数将转换为double。

  2. 否则,如果任一操作数的类型为float,则另一个操作数将转换为float。

  3. 否则,如果任一操作数的类型为long,则另一个操作数将转换为long。

  4. 否则,两个操作数都转换为int类型。

a++;++a

这里的类型就是变量的类型。再次按照JLS 15.15

前缀增量表达式的类型就是变量的类型。

前缀递减表达式的类型就是变量的类型。

a+=1

根据JLS 15.26.2

形式E1-op=E2的复合赋值表达式等价于E1=(T)((E1)-op(E2)),其中T是E1的类型,不同之处在于E1仅被评估一次。

因此,这里a += 1;等价于a = (byte)(a+1);,因为它是隐式完成的。

最新更新