106

How does a Java if statement work when it has an assignment and an equality check OR-d together??

public static void test() {
    boolean test1 = true; 
    if (test1 = false || test1 == false) {
        System.out.println("TRUE");
    } else {
        System.out.println("FALSE");
    }       
}

Why is this printing FALSE?

James Webster
  • 31,873
  • 11
  • 70
  • 114
RoHaN
  • 1,356
  • 2
  • 11
  • 21
  • 1
    Run and check. See what boolean value is printed if you assign false and if you assign true. Then read on how OR works. – Pratik Apr 16 '15 at 09:24
  • 2
    I would like to tell that this code on debug mode gives TRUE value and on Running mode gives FALSE value... Why it is so ???... (I put my breakpoint on if condition)... – CoderNeji Apr 16 '15 at 09:38
  • `test1=false`, `test1==false` is `false`, `false || false` is `false or false` which is `false`. – Jared Burrows Apr 17 '15 at 03:23
  • I know you weren't asking for advice, but as the answers below identify a precedence issue, here are a couple of practices that have helped me avoid trouble (when I stick to these): (1) always use parentheses when not 100% certain of precedence or for easier legibility to help other developers. Don't assume others will remember precedence rules for all operators (2) if-assignments should generally be avoided to reduce confusion except for very simple if-conditions. There are some common exceptions (especially with simple checks for I/O, networking, etc). Just my two cents. – rimsky Apr 17 '15 at 05:51
  • because `test1 = true` – jono Apr 17 '15 at 06:54
  • Of course the most pertinent point is that this would fail code review and the author would be sent away and told to come back with something more sensible. – Qwerky Apr 29 '15 at 08:24

4 Answers4

190

The expression is not parsed the way you think. It's not

(test1=false) || (test1 == false)

in which case the result would have been true, but

test1 = (false || test1 == false)

The value of false || test1 == false expression is computed first, and it is false, because test1 is set to true going into the computation.

The reason it is parsed this way is that the precedence of the || is lower than that of the == operator, but higher than the precedence of the assignment operator =.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 2
    +1 @RohanFernando, please also note that if you would add brackets around the assignment like so: `((test1 = false) || test1 == false)` the overall value would be `true`. – ArnonZ Apr 16 '15 at 09:35
  • 1
    Please write the reason why parsing happens so...Is it because of the priority order of operators? – kondu Apr 16 '15 at 09:41
  • 3
    @kondu That's a fair follow-up question, I edited to add a link to a precedence table, which shows that `==` is above `||`, but `=` is below `||`. – Sergey Kalinichenko Apr 16 '15 at 09:45
  • The final paragraph is misleading, in the sense that to understand why the second parsing is chosen rather than the first, it suffices to know the (easily remembered) rule that assignment has lower precedence any non-assignment operator (here `||`). The relative precedence of `||` and `==` is only relevant to show that parsing is **not** as in `test1 = ((false || test1) == false)`, which I don't think anybody would reasonably expect (by the way that relative precedence, or more generally that `||`, `&&` have lower precedence than relations, is also easy to remember, since used all the time). – Marc van Leeuwen Apr 16 '15 at 14:22
  • 1
    @MarcvanLeeuwen The relative precedence of `||` and `==` vs `||` and `=` explains why this behaves differently from the (common) case of `a == b || c == d`. – Aaron Dufour Apr 16 '15 at 16:40
  • @MarcvanLeeuwen I am, for the record, not the author of this answer. – Aaron Dufour Apr 17 '15 at 16:49
  • People keep saying that `false || test1 == false` evaluates to `false` because `test1` is set to `true` prior. But `||` operator short circuiting is at play here isn't it? It evaluates to `false` purely because the left operand is hard coded to `false`. The right hand operand `test1 == false` is never evaluated. – Adam Smith Apr 22 '15 at 23:20
  • @AdamSmith Short circuiting is applicable to `||` only when the first part evaluates to `true`. It is `&&` that short-circuits on `false`. – Sergey Kalinichenko Apr 23 '15 at 00:09
  • @dasblinkenlight Man I always get my `||`'s and `&&`'s mixed up! Thanks mate. – Adam Smith Apr 23 '15 at 01:29
83

This is a precedence issue, basically. You're assuming that your code is equivalent to:

if ((test1 = false) || (test1 == false))

... but it's not. It's actually equivalent to:

if (test1 = (false || test1 == false))

... which is equivalent to:

if (test1 = (false || false))

(because test1 is true to start with)

... which is equivalent to:

if (test1 = false)

which assigns the value false to test1, with the result of the expression being false.

See the Java tutorial on operators for a useful table of operator precedence.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
2

please have a look over precedence of operators

Expression test1 = false || test1 == false will evaluate in following step.

STEP:1- test1 = false || test1 == false //precedence of == is highest

STEP:2- test1 = false || false// Operator || have higher precedence

STEP:3- test1 = false

STEP:4- false

Since boolean value of expression becomes false.So else statement is being executed.

-11

(test1 = false || test1 == false) returns false, because both of them are false.(test1 = false || test1 == true) this is true because one of them is true

Den
  • 1
  • 4
  • 1
    Completely wrong. Why would you answer with such incorrect information days after the question has received two high quality answers which describe what happens? – l4mpi Apr 19 '15 at 12:35
  • 5
    Two answers of such low quality do not deserve individually written comments. You do realize your answer is nonsense, right? If not, carefully read the two answers by Jon and blinkenlight. – l4mpi Apr 19 '15 at 14:49