views:

341

answers:

5

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.

+7  A: 

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
+20  A: 

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
Are you sure there are an extra pair of parentheses in the last example? I thought assignment has the last precedence in Java...
Carlos Heuberger
@Carlos: Good catch. Maybe I'm so used to deliberately putting it in that I've never tried without :)
Jon Skeet
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
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
@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
You can avoid the danger of if(b == c) by instead using something like if(!(b ^ c)).
ILMTitan
@ILMTitan: Yes, but if you're thinking enough about it to write that, chances are you'll get it right anyway :)
Jon Skeet
+1  A: 

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
+1  A: 

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
+1  A: 

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