Skip to main content
Logo image

Section 4.5 if statement traps and pitfalls

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.

Subsection 4.5.1 Always use braces

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:
if (someBoolean)
  doSomething();
is equivalent to this:
if (someBoolean) {
  doSomething();
}
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:
if (someBoolean)
  System.out.println("About to do something.");
  doSomething();
Despite the structure suggested by the indentation, that is actually equivalent to this:
if (someBoolean) {
  System.out.println("About to do something.");
}
doSomething();
Now the doSomething, which used to be controlled by the if, is always run and the if only controls the println.
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.

Subsection 4.5.2 Dangling elses

Always using braces also avoids another problem known as a dangling else that occurs when an if is nested inside another if without braces.
Consider these two bits of code:
if (someBoolean)
    if (anotherBoolean)
        doSomething();
else
    doSomethingElse();
Listing 4.5.1.
if (someBoolean)
    if (anotherBoolean)
        doSomething();
    else
        doSomethingElse();
Listing 4.5.2.
Based on the indentation, you might expect those to be equivalent to these two:
if (someBoolean) {
    if (anotherBoolean) {
        doSomething();
    }
} else {
    doSomethingElse();
}
Listing 4.5.3.
if (someBoolean) {
    if (anotherBoolean) {
        doSomething();
    } else {
        doSomethingElse();
    }
}
Listing 4.5.4.
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.

Subsection 4.5.3 Watch out for extra semicolons

Also be careful not to write:
if (someBoolean);
    doSomething();
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:
if (someBoolean)
    ;
doSomething();
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:
if (someBoolean); {
    doSomething();
}
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:
if (someBoolean);
{
    doSomething();
}

Subsection 4.5.4 = != ==

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.
What the programmer who created those bugs probably meant to write was this:
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:
if (hungry) {
  eat();
}

if (!hungry) {
  study();
}
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().โ€

Subsection 4.5.5 Summary

  • 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.
  • Consistently using braces also prevents dangling elses that donโ€™t pair up with the right if.
  • Be careful not to put in a semicolon ; immediately after the condition in the if even if it is on a line by itself.
  • Avoid using == in the condition of an if statement since itโ€™s easy to mistakenly use an = instead.

Subsection 4.5.6 Practice

Activity 4.5.1. Fix the if bugs.

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.
You have attempted of activities on this page.