3.1.3 运算符的优先级顺序
到目前为止,我们已经学习了Java语言的好几种运算符,包括算术运算符、赋值运算符、逻辑运算符、关系运算符等基础运算符,并且在书写赋值语句时都没添加圆括号,显然是默认了先完成算术运算、逻辑运算、关系运算,最后才开展赋值操作。也就是说,在这4类运算符中,赋值运算符的优先级最低。那么其他3种运算符的优先级顺序又是如何排列的呢?
首先来看算术运算符。Java中的算术运算符主要包括正号、负号、加号、减号、乘号、除号以及取余数符号。对于数学上的四则运算来说,大家早已熟知乘法和除法的优先级高于加法和减法,它们在Java编程中的优先级顺序也是如此,因为取余数运算依赖于除法操作,所以取余数运算跟乘除运算的优先级是一样的。另外,还有正号和负号运算,其实主要是负号运算的优先级,数学上约定俗成负数可以直接参与四则运算,这意味着负号作为数字前面的减号,它的优先级比四则运算 要高。
于是算术运算符内部各符号的优先级顺序依次为:正号(+)、负号(-)>乘号(*)、除号(/)、取余数符号(%)>加号(+)、减号(-)。下面是演示算术运算符优先级的代码例子(完整代码见本章源码的src\com\control\logic\Priority.java):
// 比较加减乘除以及取余数运算的优先级顺序 int fiveArithmetic=7+5-4*6/3%9; // 等价于“7+5-(4*6/3%9)” System.out.println("fiveArithmetic="+fiveArithmetic); // 比较负号与乘除运算的优先级顺序 int negativeArithmetic=-8/4+2*-3; // 等价于“(-8)/4+2*(-3)” System.out.println("negativeArithmetic="+negativeArithmetic);
再来看关系运算符。关系符号包括等号、不等号、大于号、小于号等,它们互相之间的优先级是一样的。把关系运算符跟算术运算符作比较,按惯例应当是大于号、小于号和等于号不如加号、减号、乘号、除号优先,Java代码中的关系运算优先级也确实低于算术运算。也就是说,某个式子要等到加减乘除计算完毕,接下来才会开展大于、等于和小于的关系比较。下面是比较算术运算符和关系运算符优先级的代码示例:
// 以下比较算术运算符和关系运算符的优先级顺序 boolean greaterResult=1+2>3+4; // 等价于“(1+2)>(3+4)” System.out.println("greaterResult="+greaterResult); boolean lessResult=1+2<3+4; // 等价于“(1+2)<(3+4)” System.out.println("lessResult="+lessResult);
接着看逻辑运算符。由于逻辑运算的与或非操作只对布尔变量生效,因此跟操作数值变量的算术运算没有可比性,布尔类型与数值类型二者井水不犯河水,完全是风马牛不相及。故逻辑运算只能与关系运算一较高下。因为关系运算的计算结果是布尔类型的,同时逻辑运算的操作元素也为布尔类型的,所以仅凭感觉就可认为关系运算优先于逻辑运算。这个推理的确适用于“与”“或”“异或”这3种逻辑运算,但并不适用于“非”运算,缘由在于“非”运算只有一个操作数。凡是只有一个操作数的运算符都归类为一元操作符,而一元操作符的优先级要高于二元操作符,因此负号运算比乘除运算优先,同理“非”运算也比大于、等于、小于优先。但凡布尔变量前面出现了感叹号“!”,那么一定会先对该变量做“非”运算,除非有一个圆括号把感叹号后面的式子括起来。
于是逻辑运算最终的优先级顺序为:逻辑非运算符(!)>关系运算符(含等号、不等号)>其他逻辑运算符(含与符号(&)、或符号(|)、异或符号(^))。下面是比较逻辑运算符和关系运算符的优先级的代码:
// 比较逻辑与运算符以及关系运算符的优先级顺序 boolean andResult=1>2&3<4; // 等价于“(1>2)&(3<4)” System.out.println("andResult="+andResult); // 比较逻辑或运算符以及关系运算符的优先级顺序 boolean orResult=1>2|3<4; // 等价于“(1>2)|(3<4)” System.out.println("orResult="+orResult); // 比较逻辑异或运算符以及关系运算符的优先级顺序 boolean xorResult=1>2^3<4; // 等价于“(1>2)^(3<4)” System.out.println("xorResult="+xorResult); // 比较逻辑非运算符以及关系运算符的优先级顺序 boolean zhen=true; boolean jia=false; boolean notResult=zhen==!jia; // 等价于“zhen==(!jia)” System.out.println("notResult="+notResult);
总结一下,倘若没有圆括号加以约束,那么对于数值变量来说,几种运算符的优先级顺序依次为:正号、负号>乘号、除号、取余号>加号、减号>大于号、等号、小于号、不等号>各种赋值符号;对于布尔变量来说,相关运算符的优先级顺序依次为:逻辑非>等号、不等号>逻辑与、逻辑或、逻辑异或>各种赋值符号。把这些运算符放到一起,则它们的优先级顺序排列见表3-2。
表3-2 几种运算符的优先级排序