8

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
  • 4
    This raises the point that in any sort of non-trivial expression like that, it's a good idea to declare your intent with parentheses. So even if you intended (func1() || (func2() && func3()), you make it explicit and clear to programmers who come along later that your code is working as intended. Commented May 12, 2009 at 13:54

9 Answers 9

25

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)
Sign up to request clarification or add additional context in comments.

3 Comments

For the avoidance of doubt, this is because && has higher precedence than ||. Associativity is, in both cases, left-to-right.
I mention this because otherwise this post would lead to the question of, why (A || (B && C)) as opposed to ((A || B) && C).
(It's important to night that it is precedence which is important here, no associativity doesn't get a look in. IMO, expressions such as a || b && c and a && b || c (which is `(a && b) || c) are confusing and the compiler should complain.)
6

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.

Comments

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().

Comments

2

http://en.wikipedia.org/wiki/Short-circuit_evaluation

Comments

2

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.

Comments

2

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

1 Comment

It won't always shortcut. It's evaluating according to precedence rules. I don't have a java compiler handy, but I believe that (falsefunc() && true1() || true2()) will evaluate falsefunc() then true2().
1

short answer: short-circuit evaluation

since func1() yelds true there is not need to continue evaluation since it is always true

Comments

1

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.

Comments

0

If you want all functions to be executed you can drop the short-cut variants

if (func1() | func2() & func3()) {

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.