问题
Why doesn't func3 get executed in the program below? After func1, func2 doesn't need to get evaluated but for func3, shouldn't it?
if (func1() || func2() && func3()) {
System.out.println("true");
} else {
System.out.println("false");
}
}
public static boolean func1() {
System.out.println("func1");
return true;
}
public static boolean func2() {
System.out.println("func2");
return false;
}
public static boolean func3() {
System.out.println("func3");
return false;
}
回答1:
You're using a short-circuited or. If the first argument is true, the entire expression is true.
It might help if I add the implicit parentheses that the compiler uses
Edit: As Chris Jester-Young noted, this is actually because logical operators have to left-to-right associativity:
if (func1() || (func2() && func3()))
After func1 returns, it becomes this:
if (true || (func2() && func3()))
After evaluating the short-circuited or, it becomes:
if (true)
回答2:
Java functions are evaluated according to precedence rules
because "&&" is of higher precendence than "||", it is evaluated first because you did not have any brackets to set explicit precedence
so you expression of
(A || B && C)
which is
(T || F && F)
is bracketed as
(T || (F && F))
because of the precedence rules.
Since the compiler understands that if 'A == true' it doesn't need to bother evaluating the rest of the expression, it stops after evaluating A.
If you had bracketed ((A || B) && C)
Then it would evaluate to false.
EDIT
Another way, as mentioned by other posters is to use "|" and "&" instead of "||" and "&&" because that stops the expression from shortcutting. However, because of the precedence rules, the end result will still be the same.
回答3:
Java short-circuits boolean expressions. That means that, once func1()
is executed and returns true
, the rest of that boolean doesn't matter since you are using an or
operator. No matter what func2() && func3()
evaluates to, the whole expression will evaluate to true
. Thus, Java doesn't even bother evaluating the func2()
or func3()
.
回答4:
http://en.wikipedia.org/wiki/Short-circuit_evaluation
回答5:
You're using the shortcut-operators || and &&. These operators don't execute the rest of the expression, if the result is already defined. For || that means if the first expression is true and for && if the first expression is false.
If you want to execute all parts of the expression use | and & instead, that is not shortcut.
回答6:
Java uses Lazy evaluation.
Since Func1 always returns true, the entire expression MUST be true, so it shortcuts the rest of the expression.
true || (???)
and
false && (???)
will always shortcut.
To turn off shortcut evaluation, use | and & instead of || and &&
We can use this to good effect:
String s;
if (s != null && !s.equals("")) ...
Meaning that if s is null, we won't even have to try to call s.equals, and we won't end up throwing an NullPointerException
回答7:
short answer: short-circuit evaluation
since func1() yelds true there is not need to continue evaluation since it is always true
回答8:
If function 1 always returns true, then Java doesn't need to evaluate the rest of the expression to determine that the whole expression will be true.
回答9:
If you want all functions to be executed you can drop the short-cut variants
if (func1() | func2() & func3()) {
来源:https://stackoverflow.com/questions/852734/what-is-wrong-with-the-short-circuit-logic-in-this-java-code