5

This is my first post here so please forgive any protocol errors.

My question is simply trying to understand what is happening with the following Java code. I fully understand that the use of parentheses would clarify everything, but the resulting output seems to fly in the face of convention regarding Java order of operations.

public class Tester
{
   public static void main(String[] args)
   {
    int total=9, num=13;
    if (total>4 || ++num>15 && total>0)
    {
           System.out.println("short");
    }
    System.out.println(num);
   }
}

The output is: short 13

It is obvious the ++num did not execute. If strict order of operations had been observed it should have been the first thing to happen. It didn't. So next is the &&. If the && is done by order of precedence over the ||, then the same...the ++num should happen first. It didn't. So, to me it seems the output was determined with the || executed first, shortciruiting the ++num and then, working with the &&, resulted in the short being printed. Were the order of operation rules simply ignored and the Boolean expression executed left to right? Is the increment operator causing the irregular behavior?

Thanks for any insight as to what is actually going on with this code.

3
  • I do understand the optimization done by the short circuit OR. But isn't it weird anyway? The prefixed operator ++ behaves like it had a var = var + 1 one line above of where it appears in most of the cases. The same code in C++ yields 14. Could someone comment on this difference between C++ and Java? Commented Aug 7, 2012 at 1:54
  • @AndréOriani you sure? ideone.com/NBLpA Commented Aug 7, 2012 at 4:04
  • @veer Not now :) I need to check the gcc on my Mac, but the two Ubuntus I tested (gcc 4.4.3 and 4.6.3) they both rendered: subq $16, %rsp movl $9, -4(%rbp) movl $13, -8(%rbp) cmpl $4, -4(%rbp) jg .L2 *addl $1, -8(%rbp)* cmpl $15, -8(%rbp) jle .L3 cmpl $0, -4(%rbp) jle .L3 For the if. Id est. ++ only happens after the ||. Perhaps I mistook the output of my java program using |. Too much coffee :) Commented Aug 7, 2012 at 17:24

5 Answers 5

6

This has nothing to do with precedence/associativity (which deals with how expressions are parsed)... this has to do with Java evaluation order -- which is left to right. You appear to be misunderstanding how short-circuit logic works.

The && and || operators perform Conditional-AND and Conditional-OR operations on two boolean expressions. These operators exhibit "short-circuiting" behavior, which means that the second operand is evaluated only if needed.


Now, let's attempt to evaluate this expression incrementally...

total > 4 || ++num > 15 && total > 0

Since total > 4 evaluates to true, the condition evaluates to true and the if branch is taken immediately rather than evaluating the rest of the conditional.

If you change total to equal 4, then the left-operand (total > 4) of the short-circuit OR is false and thus it evaluates the right-operand (++num > 15 && total > 0).

If you change num to equal 15, then the short-circuit AND left-operand (++num > 15) evaluates to true and thus it finally evaluates the AND right-operand (total > 0) to determine whether the conditional is true. If total > 0 is false, then the conditional is also false.

Below is the code rewritten for clarity to highlight the flow.

if (total > 4) {
  System.out.println("short");
} else {
  if (++num > 15) {
    if (total > 0) {
      System.out.println("short");
    }
  }
}
System.out.println(num);

You can read more on Java conditional operators in the relevant Java Tutorial.

Sign up to request clarification or add additional context in comments.

4 Comments

This answer is what I felt like is happening. It is solving left to right rather than by precedence. The OR short circuits past the ++num leaving it at 13 because the total>4 is true and then that true is used in the && expression to give the final output.
@user1580609 see my original post for simple code that is functionally equivalent.
Wow! I thought I read the whole thing but your code is great. So the AND really never is even accessed. I never would have guessed this was what was happening. Thanks veer!
PS @user1580609 since you appear newer here, please don't forget to mark the answer accepted which helped most in solving the problem.
4

By using the double or (||), you activate java's short circuiting; (use a single | if you don't want this). As soon as it gets to a point where everything is true, and it hits a short circuit or (||), (or somethings false, and it hits a short circuit & (&&)), it will break out. So In your case, total is bigger than 4, so it stops there (due to the ||), and returns true to the if statement, and prints out short; it never reaches the part that increments the num variable, as it sees no need to check that

2 Comments

I agree, but what about the &&? The OR evaluates true, shortcircuiting the ++num, but then it has to finish the expression does it not?
As SOON as it hits the short cicruit, it stops. It reads left to right, so it reads it as total>4 || (++num>15 && (total>0)). If the first one was false, it'd continue on, looking for that to be true, but since we already got the true value that we need in || operation, it stops there
3

What's going on is short-circuit evaluation. total > 4 is true, making the entire conditional true. We don't even need to look at what follows after ||. This is a very common run-time optimization also present in C, C++, and Javascript (among many many others). You observed its' side-effect.

Note that short-circuiting can be used to your advantage (checking left-side of the || or && for a (non-)null value, for example) or it can confuzzle you (like it did in your question). Use it wisely, young padawan.

2 Comments

I understand shortcicuiting. If it shortcircuits it does as you say. My question is why did it do the OR in front of the AND when precedence says do the AND first??
What you have up there is (primarily) a logical conditional that will return either true of false, not an arithmetic operation that needs to obey the mathematical order of operations. Conditionals are evaluated left-to-right, per docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html
0

the computer will under you boolean expression like this total>4 || (++num>15 && total>0) . It is like the expression in standard SQL. It finds the && and grabs 2 expressions on the left and right then put them in a bracket like i just did. In your code, total=9>4 and ++num=14<15 and total=9>0 so the result is true ||(false && true) = true. The terminal prints out "short" and num which is 13.

Hope my answer will help you. If i am wrong, please correct me

1 Comment

Your answer is what I thought should happen by precedence. But if the AND happens first as you show it, why did the output print num as 13 if the increment operator was executed?
0

i think it doesn't change the actual value of the variable when using in the if clause . The value stored in the memory remains the same. it is like num+1>15 in the expression

1 Comment

You may (and should) comment on your first answer, rather than add another, if you need to clarify or add to your previous answer. Please don't forget to read the F.A.Q.s (the link is up by your name).

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.