我们已经掌握了所有的 Java 运算符,在实际编程过程中我们会经常使用这些运算符来完成不同的运算功能。有些运算使用一个运算符便能实现,但有时需要若干运算符组合使用来实现某种运算,这时就涉及运算符优先级的问题。

比如“int c = 4 > 3 ? 1 : 2;”,这是非常常见的条件运算符和赋值运算符结合的使用方式,根据条件判断以决定将哪个数值赋值给变量 c。

看下面这个实例:

public class OperatorPriorityTest {

public static void main(String[] args) {

int a = 0;

int b = 0;

if (a + 1 == 1 && b == 0) {

System.out.println("先执行 + 运算符 ");

System.out.println("接着执行第一个 == 运算符 ");

System.out.println("再执行第二个 == 运算符 ");

System.out.println("最后执行 && 运算符 ");

}

}

}

输出结果为:

先执行 + 运算符

接着执行第一个 == 运算符

再执行第二个 == 运算符

最后执行 && 运算符

我们主要关注if (a + 1 == 1 && b == 0),if 条件一共包含了 4 个运算符,根据运算符的优先级高低,程序执行时会先执行 + 运算符,接着执行第一个 == 运算符,再执行第二个 == 运算符,最后执行 && 运算符。

Java 中的运算符的优先级可以分为 14 个,优先级越高越先执行。下表展示了 Java 运算符的优先级,优先级取值范围为 1~14,值越小优先级越高。

表:Java 运算符优先级

优先级

运算符

结合顺序

运算符类别

1

()

从左向右

括号运算符

2

!、+(正)、-(负)、~、++、--

从右向左

逻辑、正负、自增减运算符

3

*、/、%

从左向右

算术运算符

4

+(加)、-(减)

从左向右

算术运算符

5

<<、>>、>>>

从左向右

移位运算符

6

<、<=、>、>=、instanceof

从左向右

关系运算符

7

==、!=

从左向右

关系运算符

8

&

从左向右

位逻辑运算符

9

^

从左向右

位逻辑运算符

10

|

从左向右

位逻辑运算符

11

&&

从左向右

逻辑运算符

12

||

从左向右

逻辑运算符

13

?:

从右向左

条件运算符

14

=、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=、>>>=

从右向左

赋值运算符

可以看到括号运算符的优先级是最高的,而赋值运算符的优先级则是最低的。

结合顺序是指优先级相同的情况下运算符的运算顺序,我们熟悉的数学上的运算都是从左往右的,但 Java 中有一些运算符在相同优先级的情况下是从右往左运算的。

上表中有这么多不同优先级的运算符,当它们混合使用时如何才能正确地理解这些表达式呢?比如:

public class OperatorPriorityTest2 {

public static void main(String[] args) {

int a = 3;

int b = 3;

int c = ++a + --b * a++ / b-- >> 2 % a--;

System.out.println("a=" + a);

System.out.println("b=" + b);

System.out.println("c=" + c);

}

}

输出结果为:

a=4

b=1

c=2

看到变量 c 后面长长的一串符号是不是有点迷惑?我们按优先级的高低一步步来分析,第一轮执行优先级为 2 的自增和自减运算,此时表达式变成:

c = 4 + 2 * 4 / 2 >> 2 % 5

执行后变量 a、b 分别为 4 和 1。

第二轮执行优先级为 3 的乘除取余等运算,此时表达式为:

c = 4 + 4 >> 2

第三轮执行优先级为 4 的加减法运算,执行后表达式变成:

c = 8 >> 2

第四轮执行优先级为 5 的移位运算。最后执行赋值运算且结果为 c = 2。

当有多个运算符参与运算时,执行的顺序是先考虑优先级,在相同优先级的情况下则是按结合顺序执行。继续通过下面的例子来理解结合顺序,对于从左向右的结合顺序我们在数学上早已见惯了,所以我们看看从右向左结合的例子:

public class OperatorPriorityTest3 {

public static void main(String[] args) {

int a = 3;

int b = 3;

int c = a != 3 ? b : b == 3 ? 1 : 0;

System.out.println(c);

}

}

程序里使用了两个条件运算符进行嵌套,对于“a != 3 ? b : b == 3 ? 1 : 0”,先计算“b == 3 ? 1 : 0”,得到的结果是 1,再计算“a != 3 ? b :1”,最终的结果是 1,所以变量 c 为 1。

在实际开发过程中,没必要死记硬背运算符的优先级,而且我们要尽量保证简洁地使用运算符,在多个运算符组合时也可以通过括号运算符来限制先后执行顺序,比如“a = b + c >> 2”可以写成“a = (b + c) >> 2”,这样就非常清晰了。