Java Language Pitfall - Leaving out braces: the "dangling if" and "dangling else" problems


Example

The latest version of the Oracle Java style guide mandates that the "then" and "else" statements in an if statement should always be enclosed in "braces" or "curly brackets". Similar rules apply to the bodies of various loop statements.

if (a) {           // <- open brace
    doSomething();
    doSomeMore();
}                  // <- close brace

This is not actually required by Java language syntax. Indeed, if the "then" part of an if statement is a single statement, it is legal to leave out the braces

if (a)
    doSomething();

or even

if (a) doSomething();

However there are dangers in ignoring Java style rules and leaving out the braces. Specifically, you significantly increase the risk that code with faulty indentation will be misread.

The "dangling if" problem:

Consider the example code from above, rewritten without braces.

if (a)
   doSomething();
   doSomeMore();

This code seems to say that the calls to doSomething and doSomeMore will both occur if and only if a is true. In fact, the code is incorrectly indented. The Java Language Specification that the doSomeMore() call is a separate statement following the if statement. The correct indentation is as follows:

if (a)
   doSomething();
doSomeMore();

The "dangling else" problem

A second problem appears when we add else to the mix. Consider the following example with missing braces.

if (a)
   if (b)
      doX();
   else if (c)
      doY(); 
else
   doZ();

The code above seems to say that doZ will be called when a is false. In fact, the indentation is incorrect once again. The correct indentation for the code is:

if (a)
   if (b)
      doX();
   else if (c)
      doY(); 
   else
      doZ();

If the code was written according to the Java style rules, it would actually look like this:

if (a) {
   if (b) {
      doX();
   } else if (c) {
      doY(); 
   } else {
      doZ();
   }
}

To illustrate why that is better, suppose that you had accidentally mis-indented the code. You might end up with something like this:

if (a) {                         if (a) {
   if (b) {                          if (b) {
      doX();                            doX();
   } else if (c) {                   } else if (c) {
      doY();                            doY();
} else {                         } else {
   doZ();                            doZ();
}                                    }
}                                }

But in both cases, the mis-indented code "looks wrong" to the eye of an experienced Java programmer.