12

I know that we cant use assignment operator in if statements in java as we use in any other few languages.

that is

            int a;

            if(a = 1) {  } 

will give a compilation error.

but the following code works fine, how?

           boolean b;

           if(b = true) {   }

EDIT : Is this the exception to rule that assignment cant be used in if statement.

MPelletier
  • 16,256
  • 15
  • 86
  • 137
GuruKulki
  • 25,776
  • 50
  • 140
  • 201
  • 6
    It's not a bad idea to get in the habit of putting the constant first in your if statements.... That is: if (true == b) {} and if (1 == a) {} This habit guarantees that the compiler will smack you if you write = instead of ==. – O. Jones Mar 06 '10 at 21:12
  • 5
    @Ollie: opinions widely differ on that one. As far as readability is concerned, this *is* a bad idea. Furthermore, it offers no benefit in languages such as Java since no confusion can arise here. I mean, nobody ever writes a test as `if (a == true)`, right? – Konrad Rudolph Mar 06 '10 at 21:56
  • @Konrad. You're right in Java, but for this C retread who works in PERL and some other languages, it's saved me lots of times. – O. Jones Mar 11 '10 at 02:54
  • 2
    Doesn't work in a huge variety of cases, like `if ( $a == $b )`. Horrible to read, nobody says '5 is a'. It's easier to just be more careful when writing `if` conditions, IMO. – rjh Apr 06 '10 at 17:18
  • @Ollie most compilers these days have an option to warn you if you write `if(foo = x)` or something like that. – Spudd86 Jun 17 '10 at 20:38

5 Answers5

40

Because the "result" of an assignment is the value assigned... so it's still a boolean expression in the second case. if expressions require the condition to be a boolean expression, which is satisfied by the second but not the first. Effectively, your two snippets are:

int a;

a = 1;
if (a) { }

and

boolean b;

b = true;
if (b) { }

Is it clear from that expansion that the second version will compile but not the first?

This is one reason not to do comparisons with true and false directly. So I would always just write if (b) instead of if (b == true) and if (!b) instead of if (b == false). You still get into problems with if (b == c) when b and c are boolean variables, admittedly - a typo there can cause an issue. I can't say it's ever happened to me though.

EDIT: Responding to your edit - assignments of all kinds can be used in if statements - and while loops etc, so long as the overall condition expression is boolean. For example, you might have:

String line;
while ((line = reader.readLine()) != null)
{
    // Do something with a line
}

While I usually avoid side-effects in conditions, this particular idiom is often useful for the example shown above, or using InputStream.read. Basically it's "while the value I read is useful, use it."

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 3
    Are you sure there are an extra pair of parentheses in the last example? I thought assignment has the last precedence in Java... – user85421 Mar 06 '10 at 21:05
  • 2
    @Carlos: Good catch. Maybe I'm so used to deliberately putting it in that I've never tried without :) – Jon Skeet Mar 06 '10 at 21:32
  • I usually think of that idiom (and use it when the analogy fits) in terms of the iterator's hasNext and next methods - it's basically implementing a combination of those for something that isn't explicitly an iterator (and I sure wish readers had implementation of that interface added in later versions). – Carl Mar 06 '10 at 23:28
  • Additionally, in some languages (C, C++) an integer can be substituted for a boolean value, with 0 being false and non-0 being true. Which widely increases the chances of the =/== bug. – mtruesdell Mar 07 '10 at 01:42
  • @mtruesdell: Indeed, although I believe most C and C++ compilers will warn you unless you have an extra pair of parentheses to reinforce that it's deliberate... at least if you have warnings turned up high enough. – Jon Skeet Mar 07 '10 at 07:15
  • You can avoid the danger of if(b == c) by instead using something like if(!(b ^ c)). – ILMTitan Mar 08 '10 at 19:25
  • @ILMTitan: Yes, but if you're thinking enough about it to write that, chances are you'll get it right anyway :) – Jon Skeet Mar 08 '10 at 19:47
10

For if you need an expression that evaluates to boolean. b = true evalueates to boolean but a = 1 evaluates to int as assignments always evaluate to the assigned values.

Gumbo
  • 643,351
  • 109
  • 780
  • 844
1

The reason the second code works okay is because it is assigning 'b' the value of true, and then comparing to see if b is true or false. The reason you can do this is because you can do assignment operators inside an if statement, AND you can compare against a boolean by itself. It would be the same as doing if(true).

JasCav
  • 34,458
  • 20
  • 113
  • 170
1

In java, you don't have implicit casting. So non-boolean values or not automatically transformed to booleans.

In the first case, the result of the statements is an int, which is non-boolean, which will not work. The last case, the result is boolean, which can be evaluated in an if-statement.

Ikke
  • 99,403
  • 23
  • 97
  • 120
1

The rule is not that "assignment can't be used in an if statement", but that "the condition in an if statement must be of type boolean". An assignment expression produces a value of the type being assigned, so Java only permits assignment in an if statement if you're assigning a boolean value.

This is a good reason why the style if (foo == true) should be avoided, and instead simply write if (foo).

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285