Java中的复合赋值运算符
复合赋值运算符为分配算术或按位运算运算符的结果提供了更短的语法。它们在将结果分配给第一个操作数之前对两个操作数执行操作。
以下是Java中所有可能的赋值运算符:
1. += (compound addition assignment operator)
2. -= (compound subtraction assignment operator)
3. *= (compound multiplication assignment operator)
4. /= (compound division assignment operator)
5. %= (compound modulo assignment operator)
6. &= (compound Bitwise & assignment operator)
7. |= (compound Bitwise | assignment operator)
8. ^= (compound Bitwise ^ assignment operator)
9. >>= (compound right-shift assignment operator)
10. >>>=(compound right-shift filled 0 assignment operator)
11. <<=(compound left-shift assignment operator)
所有复合赋值运算符的实现
// Java program to illustrate
// Compound assignment operators
class Main {
public static void main(String args[])
{
byte b = 120;
b += 10;
byte b1 = 120;
b1 *= 10;
short s = 330;
s -= 30;
byte b2 = 127;
b2 %= 7;
byte b3 = 120;
b3 &= 40;
short s1 = 300;
s1 ^= 100;
byte b4 = 127;
b4 >>= 3;
short s2 = 200;
s2 <<= 3;
short s3 = 300;
s3 >> >= 4;
System.out.println(b);
System.out.println(b1);
System.out.println(b2);
System.out.println(b3);
System.out.println(b4);
System.out.println(s);
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
}
}
输出:
-126
-80
1
40
15
300
328
1600
18
解决复合赋值运算符的规则
在运行时,表达式以两种方式之一进行评估。取决于编程条件:
- 如果左侧操作数表达式不是数组访问表达式,则:
- 首先,评估左侧操作数以产生变量。如果这个求值突然完成,那么赋值表达式也会因为同样的原因而突然完成;不计算右侧操作数,也不发生赋值。
- 否则,将保存左侧操作数的值,然后计算右侧操作数。如果这个求值突然完成,那么赋值表达式也会因为同样的原因而突然完成并且没有赋值发生。
- 否则,左侧变量的保存值和右侧操作数的值用于执行复合赋值运算符。如果此操作突然完成,则赋值表达式出于同样的原因突然完成并且不发生赋值。
- 否则,将二进制运算的结果转换为左侧变量的类型,进行值集转换为适当的标准值集,并将转换结果存储到变量中。
- 如果左侧操作数表达式是数组访问表达式,则:
- 首先,评估左侧操作数数组访问表达式的数组引用子表达式。如果这个求值突然完成,那么赋值表达式也会因为同样的原因而突然完成; (左侧操作数数组访问表达式的)索引子表达式和右侧操作数不被计算并且不发生赋值。
- 否则,计算左侧操作数数组访问表达式的索引子表达式。如果此评估突然完成,则赋值表达式出于同样的原因突然完成,并且不会评估右侧操作数并且不会发生赋值。
- 否则,如果数组引用子表达式的值为 null,则不发生赋值并抛出 NullPointerException。
- 否则,数组引用子表达式的值确实引用了一个数组。如果索引子表达式的值小于零,或者大于或等于数组的长度,则不发生赋值并抛出 ArrayIndexOutOfBoundsException。
- 否则,索引子表达式的值用于选择数组引用子表达式的值所引用的数组组件。保存该组件的值,然后计算右侧操作数。如果这个求值突然完成,那么赋值表达式也会因为同样的原因而突然完成并且没有赋值发生。
示例:使用复合赋值运算符解析语句
我们都知道,每当我们将较大的值分配给较小的数据类型变量时,我们必须执行显式类型转换才能获得没有任何编译时错误的结果。如果我们没有执行显式类型转换,那么我们将得到编译时错误。但是在复合赋值运算符的情况下,内部类型转换将自动执行,即使我们将较大的值分配给较小的数据类型变量,但可能会丢失数据信息。程序员不负责执行显式类型转换。让我们看下面的例子来找出普通赋值运算符和复合赋值运算符之间的区别。
E1 op= E2 形式的复合赋值表达式等价于 E1 = (T) ((E1) op (E2)),其中 T 是 E1 的类型,除了 E1 只计算一次。
例如,下面的代码是正确的:
short x = 4;
x += 6.6;
并导致 x 的值为 7,因为它等效于:
short x = 4;
x = (short)(x + 6.6);
x=10
因为这里是 double 的 6.6 会自动转换为 short 类型,而无需显式类型转换。
参考:什么时候需要类型转换?
// Java program to illustrate the
// behavior of normal addition operator
public class Test {
public static void main(String[] args)
{
// Normal assignment operator
byte b = 10;
b = b + 10;
System.out.println(b);
}
}
输出:
error: incompatible types: possible lossy conversion from int to byte
说明:在上面的例子中,我们使用的是普通的赋值运算符。在这里,我们将一个 int (b+1=20) 值分配给字节变量(即 b),这会导致编译时错误。在这里,我们必须进行类型转换才能得到结果。
// Java program to illustrate the
// behavior of compound addition assignment operator
public class Test {
public static void main(String[] args)
{
// compound assignment operator
byte b = 10;
b += 10;
System.out.println(b);
}
}
输出:
20
说明:在上面的例子中,我们使用了复合赋值运算符。在这里,我们将一个 int (b+1=20) 值分配给字节变量(即 b),除此之外,我们得到的结果为 20,因为在复合赋值运算符中,类型转换是由编译自动完成的。在这里,我们不必进行类型转换即可获得结果。
// Java program to illustrate the
// behavior of normal multiplication operator
public class Test {
public static void main(String[] args)
{
// Normal multiplication operator
short s = 1270;
s = s * 100;
System.out.println(s);
}
}
输出:
Error: incompatible types: possible lossy conversion from int to short
// Java program to illustrate the
// behavior of compound multiplication operator
public class Test {
public static void main(String[] args)
{
// Compound multiplication operator
short s = 1270;
s *= 100;
System.out.println(s);
}
}
输出:
-4072
// Java program to illustrate the
// behavior of normal addition operator on float
public class Test {
public static void main(String[] args)
{
// Normal addition operator
float f = 1270.00f;
f = f + 127.00;
System.out.println(f);
}
}
输出:
error: incompatible types: possible lossy conversion from double to float
// Java program to illustrate the
// behavior of compound addition operator on float
public class Test {
public static void main(String[] args)
{
// Compound addition operator
float f = 1270.00f;
f += 127.00;
System.out.println(f);
}
}
输出:
1397.0
参考: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.26.2