Search code examples
javaoperator-precedenceshort-circuiting

Order of Operations with Logic in Java Confused


I have an order of operations problem from a quiz and the explanation is not exactly helpful. Here is the code:

package com.udayan.oca;

public class Test {
     public static void main(String [] args) {
         int a = 2;
         boolean res = false;
         res = a++ == 2 || --a == 2 && --a == 2;
         System.out.println(a);
     }
}

It says it prints 3 which it does because I tested that but I do not understand how. Here is their explanation:

a++ == 2 || --a == 2 && --a == 2;

[Given expression]. (a++) == 2 || --a == 2 && --a == 2;

[Postfix has got higher precedence than other operators].

(a++) == 2 || (--a) == 2 && (--a) == 2;

[After postfix, precedence is given to prefix].

((a++) == 2) || ((--a) == 2) && ((--a) == 2);

[== has higher precedence over && and ||].

((a++) == 2) || (((--a) == 2) && ((--a) == 2));

[&& has higher precedence over ||].

Let's start solving it: ((a++) == 2) || (((--a) == 2) && ((--a) == 2));

[a=2, res=false].

(2 == 2) || (((--a) == 2) && ((--a) == 2));

[a=3, res=false]. true || (((--a) == 2) && ((--a) == 2));

[a=3, res=false].

|| is a short-circuit operator, hence no need to evaluate expression on the right.

res is true and a is 3.

Yes, I understand short circuiting by the way so no need to explain that.

So here is my thinking however:

res = a++ == 2 || --a == 2 && --a == 2 ->
(((a++) == 2) || (((--a) == 2) && ((--a) == 2))) [a = 2]

(((a++) == 2) || ((**1** == 2) && ((--a) == 2))) [a = 1]

(((a++) == 2) || (**false** && (**0** == 2))) [a = 1] //short-circuits

(((a++) == 2) || **false**) [a = 1] //short circuits

(**false**) [a = 1]

???? Another point is that the answer key says to do a++ first then || next. a++ yah that makes sense. But I thought && is before ||.


Solution

  • res = a++ == 2 || --a == 2 && --a == 2 (res is true)
    
    1. a++ (post-increment, no) -> a = a + 1 -> it's still 2 -> when true -> it becomes 3
    2. --a (pre-increment, right to left) -> a - 1 = a -> 1
    3. --a (pre-increment, right to left) -> a - 1 = a -> 0 (its because of logical and, it never execute this part) 
    4. == (equality, left to right) -> 2 == 2 || 1 == 2 && 0 == 2 -> true || false && false
    5. && (logical and, left to right) -> false -> no more steps 
    6. || (logical or, left to right) -> true -> go to 1.
    
    // so take 3
    // moral of the story is always use paranthesis
    // op is correct for short-circuit