Dangling else & braces in Java
else binds to the nearest if; why braces prevent bugs.
One statement, no more
Without braces, an if controls exactly one statement. Indentation is only for humans: the compiler ignores whitespace. So the second println below is *not* part of the if, it always runs.
if (x > 5)
System.out.println("big");
System.out.println("done");Your turn
coins is 3. What prints?
int coins = 3;
if (coins > 10)
System.out.println("Rich!");
System.out.println("Shop opened");Nothing is printedRich! Shop openedShop opened
Show the answer
Only Shop opened. The if (false) guards just the first println. The second one *looks* guarded thanks to its indentation, but it always runs.
The dangling else
With nested ifs and no braces, an else pairs with the nearest preceding if that doesn't already have an else, whatever the indentation says. The inner if/else then becomes the single body of the outer if: if the outer condition is false, neither branch runs.
if (a > 0)
if (b > 0)
System.out.println("both");
else // belongs to if (b > 0)!
System.out.println("a not positive");Who owns this else?
age is 20, member is false. What prints?
int age = 20;
boolean member = false;
if (age >= 18)
if (member)
System.out.println("VIP");
else
System.out.println("Too young");Nothing is printedVIPToo young
Show the answer
Too young, which is a lie! The else belongs to the inner if (member). Age 20 passes the outer check, member is false, so the inner else runs. Had age been 15, *nothing* would print.
The stray semicolon
A ; right after if (...) is an empty statement: it becomes the entire body of the if. The block below is just an ordinary block that always runs. This prints "In stock" even when stock is 0.
int stock = 0;
if (stock > 0);
{
System.out.println("In stock");
}Braces every time
if (a > 0)
if (b > 0)
System.out.println("both");
else
System.out.println("no a");The else silently attaches to the inner if.
if (a > 0) {
if (b > 0) {
System.out.println("both");
}
} else {
System.out.println("no a");
}With braces, the structure you mean is the structure you get.
In real projects
In 2014 Apple shipped the "goto fail" bug: a duplicated line under a brace-less if in its TLS code always ran, skipping a crucial certificate check on iOS and macOS. That's why most style guides, including Google's Java Style Guide, require braces even for one-line bodies.
Key takeaways
- else binds to the closest unmatched if, whatever the indentation
- Without braces, an if controls exactly ONE statement
- A stray ; after if (...) is an empty statement, so the block always runs
- Always use braces, even for one-line bodies
💡 Braces are like putting things in labelled boxes: without them, the compiler decides what goes where, not your indentation.
Python made indentation part of the language itself, so code can never look one way and run another. Java chose braces instead, which is why tools like formatters and linters matter so much.
Practice questions
What does this print?
int x = 0;
if (x > 5)
System.out.println("big");
System.out.println("done");- Nothing is printed
- big done
- done
Check your answer
done. Without braces, only the first statement belongs to the if. The second println is indented, but it always runs.
What does this print?
int a = 1, b = -1;
if (a > 0)
if (b > 0)
System.out.println("both");
else
System.out.println("a not positive");- both
- a not positive
- Nothing is printed
Check your answer
a not positive. The else belongs to the inner if (b > 0), not to the outer one. a > 0 is true and b > 0 is false, so the else runs and prints a misleading message.