在学习Java中逻辑表达式中的短路机制之前, 我们必须明确一点:
就是运算符优先级与执行顺序的问题, 运算符优先级高的表达式在执行时会被视为一个整体, 但是对于除赋值符外的所有二元运算符来说, 执行的顺序始终是从左到右执行的.
比如 1 + 2 + (3 + 4) 这个式子, 括号的优先级最高, 所以括号内的表达式被视为一个整体, 执行顺序是 1+2+(整体), 先执行了1 + 2再遇到括号内的整体, 再执行整体内的表达式.
再不会混淆的前提下理解短路机制, 我们就必须先知道优先级与执行顺序没有必然联系.
实例:
/** * 测试运算符的优先级是否与执行顺序有关 * @author libertine1993 */ public class TestOrder{ public static int test(int para){ System.out.println("called with para = " + para); return para; } public static void main(String[] args){ int i = test(0) + test(1) - test(2) * test(3); System.out.println("-------------------------"); i =test(0) + test(1) + test(2) + ( test(3) - test(4) ); System.out.println("-------------------------"); i = ( test(0) - test(1) ) + test(2) + test(3) * test(4); } }
第一个表达式 " test(2) * test(3)" 拥有较高的优先级, 所以会被视为一个整体, 但是程序的执行顺序还是从左到右, 因此调用的顺序是 test(0), test(1), test(2), test(3)
第二个表达式理同第一个.
第三个表达式执行顺序是 (整体) , test(2), test(3), test(4)
对于++, --,这种运算符的解释, 也一样 a + ++b 的执行顺序是从左往右, a + (整体), 整体是++b
在明确了Java运算符优先级高的表达式会被视为整体, 但是执行顺序还是从左到右之后我们再来看Java的逻辑表达式的短路机制.
逻辑表达式的短路机制:
在Java中, 在已经能够确定整个逻辑表达式的值的情况下, 就会对整个逻辑表达式进行求值, 也就是说会有部分的条件不会被判断到, 因为我们已经能够确定整个逻辑表达式的值了(当然这种机制仍然要遵循表达式执行的顺序).
举个简单的例子:
import java.util.*; public class ShortCircuit{ public static boolean test(int para){ System.out.println("test is called with para = " + para); return para > 5; } public static void main(String[] args){ System.out.println("----------------------------------------"); //与运算的短路条件: 同一级别的逻辑表达式, 前面的条件为false, 该级别的表达式就确定为假, 后面的表达式无需运算 if(test(0) && test(6) && test(1) && test(2) && test(3)){} System.out.println("----------------------------------------"); //或运算的短路条件: 同一级别的逻辑表达式, 前面的条件为true, 该级别的表达式就确定为真, 后面的表达式无需运算 if(test(6) || test(0) || test(1) || test(2) || test(3)){} } }输出:
第一个表达式, 因为test(0) 为false, 故整个表达式的值已经确定为false, 发生了短路, 后面的条件均没有判断.
第二个表达式, 因为test(6)为true, 此时整个表达式的值已经确定为true, 同样发生短路.
接下来的例子就是我们在介绍短路机制之前, 特地要说明运算符优先级与执行顺序的原因
import java.util.*; public class ShortCircuit{ public static boolean test(int para){ System.out.println("test is called with para = " + para); return para > 5; } public static void main(String[] args){ System.out.println("----------------------------------------"); if(test(8) || test(1) && test(4)){} System.out.println("----------------------------------------"); //嵌套的逻辑表达式, 短路的判断会逐级别判断 if( (test(9) || test(6) || test(7)) || test(8) && test(1)){} /*内层逻辑表达式 test(0) && test(6) && test(7) */ } }
输出:
第一个表达式中, &&的优先级高 (关于&&的优先级高于||, 有疑惑的请拉至最下方, 参考来自Sun的官方文档给出的优先级表格), 所以test(1) && test(4) 会被当成整体, 外层的逻辑表达式是 test(8) || (整体), 故因为test(8) 为真, 整个逻辑表达式的值已确定为真, 故发生短路, 只判断了test(8)的条件.
第二个表达式说明, 短路机制的判断会发生在每一层的逻辑表达式当中(当然仍然得遵循执行顺序).内层表达式 test(9) || test(6) || test(7) 只判断了test(9) 就短路, 然后进入(整体) || test(8) && test(1) 这一层, 整体为真, 又短路.
Java官方文档运算符优先级: