While if statements are pretty simple, they do present some traps for the unwary. Luckily there are also some practices we can adopt that will make it much less likely that we will fall into those traps. In this section we discuss some of those.
Strictly speaking, the curly braces around the body of the if are not actually a part of the if syntax. They are a more general feature of Java: in any context where Java expects a single statement, it will also accept a block of statements enclosed in braces.
The body of an if is such a place that accepts either a single statement or a block enclosed in braces. So it is legal to leave out the braces if the body of the if is just one statement. Thus this:
However you should always write it the second way. Hereโs whyโif you later decide to add something, say maybe a println before the doSomething() and you arenโt careful you might end up with this:
The easiest way to avoid this kind of mistake is to always put the bodies of constructs that accept a statement or block in braces, even when they are not technically required. This includes the body of the if and the else, if any. It also applies to the loop constructs weโll discuss in the next unit. All the code you seen on the AP exam will be written in that style.
However, since indentation is not significant in Java, both of the top listings (Listingย 4.5.1 and Listingย 4.5.2) are equivalent. Itโs actually ambiguous how to interpret the top versions similar to how in English there are two ways to interpret a sentence like, โI saw the man with a telescopeโ. Does that mean I used a telescope to see the man, or I saw a man who had a telescope?
Since Java canโt ask us what we meant, it uses a rule that in cases like that, the else clause always attaches to the closest if. So both versions without braces are equivalent to Listingย 4.5.4 regardless of indentation.
But always using braces means you will be forced to write one or the other and you, and anyone else reading your code, will not have to worry about being mislead by bad indentation and wonโt have to remember how Java resolves the ambiguity.
Note the semicolon (;) at the end of the first line. Unfortunately that is legal Java code but almost certainly not what you meant. It is equivalent to:
A semicolon by itself is actually a statement. Itโs called the empty statement and it does nothing. So that code checks if someBoolean is true and if it is does nothing. Then it calls doSomething() regardless.
You can still this mistake even if you use braces but itโs probably less likely since youโd have to put the semicolon between the closing parentheses and the opening brace rather than at the end of the line:
However, some Java programmers format their code with braces on lines by themselves which would make this mistake easier to make since weโre used to putting semicolons on the ends of lines:
Another classic bug arises when we use a single equals sign = when we should have used two equals signs ==. In Java (and in many other languages) both are operators meaning they operate on some operands and produce a value.
The single = is the assignment operator, which assigns a value to a variable but it also produces a value, namely the value that was just assigned. So an expression like hungry = true has the side effect of setting hungry to true but also evaluates to true.
The double ==, on the other hand, is the equality comparison operator, which evaluates to true if both its operands are the same value and false otherwise. The expression hungry == true doesnโt change the value of hungry but evaluates to either true or false depending on hungryโs current value.
So this bug is called the = != == bug since the two operators are not the same and using one when we should have used the other is a bug. Hereโs how the bug looks in Java.
if (hungry = true) {
eat();
}
if (hungry = false) {
study();
}
The first if statement will always call eat(), regardless of what hungry was before the if. And the second will never call study(), regardless of hungryโs prior value. And both of them will clobber the old value of hungry which will probably cause some confusion down the road.
if (hungry == true) {
eat();
}
if (hungry == false) {
study();
}
By changing the = operators to ==, the code calls eat() and study() at the correct timess. However, thereโs an even better way to write these that is both simpler and avoids the possibility of falling into the = != == trap:
The point is, hungry is already a boolean. Comparing it to a literal like true doesnโt make it any more of a boolean. (Think of it this way: if you feel the need to write hungry == true why not write hungry == true == true?) And if you know that !hungry is pronunced โnot hungryโ then both of these bits of code read almost like English, maybe as spoken by a caveman: โIf hungry, eat,โ and โIf not hungry, study.โ Nobody says, โIf itโs true that Iโm hungry, eat()โ or โIf itโs false that Iโm hungry, study().โ
Always use braces ({ and }) to enclose the body of an if or else, even if itโs just one statement to avoid misleading indentation and errors when you add lines to an existing body.
The code below doesnโt work as the author intended. It was supposed to print both Wear a coat and Wear gloves but only when isCold is true. But somehow the author has fallen into all the traps mentioned in this chapter! Fix it so it does what they wanted it to.