问题
I'm wondering if it's guaranteed that in a Java program, the boolean expression on the right of a conjunction (exp2 above) will NOT be evaluated as long as the expression on the left (exp1) evaluated to false. I'm wondering because I have an expression like the following:
if (var != null && var.somePredicate())
// do something
If Java is not guaranteed to stop evaluating (var != null && var.somePredicate())
after it sees that var
is null, then it may try to evaluate var.somePredicate()
which would throw a NullPointerException.
So my question is, does Java guarantee a certain behavior when it comes to this? Or would it be safer to write
if (var != null)
{
if (var.somePredicate())
// do something
}
回答1:
From the Java Language Specification, 15.23 Conditional-And Operator &&:
The
&&
operator is like&
(§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is true.
So the language spec guarantees that the right-hand side of your expression will not be evaluated if the left hand side is false.
回答2:
No, java uses Short circuit evaluation. If expr1
is false
, expr2
will not be evaluated, thus your &&
usage is perfectly safe.
Also, if you have if (exp1 || exp2) { .. }
- exp2
will not be evaluated if exp1
is true
.
回答3:
Let us perform our own experiment by looking directly at the opcodes that are generated from this sample code:
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
generates:
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
The relevant opcodes are ifeq
for my small program. They check to see if the variables are equal to 0, and jump a certain number of operations forward if they are, in this case, to opcode 23. So if the first ifeq
evaluates to false it will jump past the second ifeq
instruction straight to the else statement.
This is called short circuit evaluation.
回答4:
If you use && or ||, java will use short-circuit evaluation (ie not evaluate the second expression unless it needs to)
If you use & or |, java will always evaluate the second expression, even if the first was true
回答5:
That's safe, Java does short circuit evaluations.
来源:https://stackoverflow.com/questions/9445145/when-java-evaluates-a-conjunction-boolean-exp1-boolean-exp2-does-it-ev