我想知道是否保证在Java程序中,只要左边的表达式(exp1)评估为false,就不会计算连接右边的布尔表达式(上面的exp2)。我想知道因为我有如下表达式:
if (var != null && var.somePredicate())
// do something
如果不确定Java在(var != null && var.somePredicate())
为空后才停止评估var
,那么它可能会尝试评估会引发NullPointerException的var.somePredicate()
。
所以我的问题是,Java在这方面是否保证某种行为?或者编写
会更安全if (var != null)
{
if (var.somePredicate())
// do something
}
答案 0 :(得分:6)
来自Java语言规范,15.23 Conditional-And Operator &&:
&&
运算符类似于&
(第15.22.2节),但仅在其左侧操作数的值为真时才计算其右侧操作数
因此语言规范保证如果左侧是假的,则不会评估表达式的右侧。
答案 1 :(得分:4)
不,java使用Short circuit evaluation。如果expr1
为false
,则不会评估expr2
,因此您&&
的使用非常安全。
此外,如果if (exp1 || exp2) { .. }
- exp2
,exp1
为true
,则不会对其进行评估。
答案 2 :(得分:2)
让我们直接查看从此示例代码生成的操作码来执行我们自己的实验:
public class Compare {
public static void main(String... args) {
boolean t = true;
boolean f = false;
if(f && t) {
System.out.println("Both true");
}
else {
System.out.println("One false");
}
}
}
javap -v
生成:
0: iconst_1
1: istore_1
2: iconst_0
3: istore_2
4: iload_2
5: ifeq 23
8: iload_1
9: ifeq 23
12: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
15: ldc #3; //String No
17: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
20: goto 31
23: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
26: ldc #5; //String Yes
28: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
31: return
我的小程序的相关操作码为ifeq
。他们检查变量是否等于0,并且如果它们是操作码23,则向前跳转一定数量的操作。因此,如果第一个ifeq
评估为假,它将跳过第二个ifeq
直接指示else语句。
这称为短路评估。
答案 3 :(得分:1)
如果您使用&&或者||,java将使用短路评估(即除非需要,否则不评估第二个表达式)
如果您使用&或者|,java将始终评估第二个表达式,即使第一个表达式为真
答案 4 :(得分:0)
这是安全的,Java会进行短路评估。