14.19 Unreachable Statements

That looks like a path.
Is that the way to reach the top from here?

—Robert Frost, The Mountain (1915)

It is a compile-time error if a statement cannot be executed because it is unreachable. Every Java compiler must carry out the conservative flow analysis specified here to make sure all statements are reachable.

This section is devoted to a precise explanation of the word "reachable." The idea is that there must be some possible execution path from the beginning of the constructor, method, or static initializer that contains the statement to the statement itself. The analysis takes into account the structure of statements. Except for the special treatment of while, do, and for statements whose condition expression has the constant value true, the values of expressions are not taken into account in the flow analysis. For example, a Java compiler will accept the code:


{
	int n = 5;
	while (n > 7) n = 2;
}

even though the value of n is known at compile time and in principle it can be known at compile time that the assignment to k can never be executed. A Java compiler must operate according to the rules laid out in this section.

The rules in this section define two technical terms:

The definitions here allow a statement to complete normally only if it is reachable.

To shorten the description of the rules, the customary abbreviation "iff" is used to mean "if and only if."

The rules are as follows:

The contained statement is reachable iff the labeled statement is reachable.

The contained statement is reachable iff the while statement is reachable and the condition expression is not a constant expression whose value is false.

The contained statement is reachable iff the do statement is reachable.

The contained statement is reachable iff the for statement is reachable and the condition expression is not a constant expression whose value is false.

One might expect the if statement to be handled in the following manner, but these are not the rules that Java actually uses:

The then-statement is reachable iff the if-then statement is reachable and the condition expression is not a constant expression whose value is false.

This approach would be consistent with the treatment of other control structures in Java. However, in order to allow the if statement to be used conveniently for "conditional compilation" purposes, the actual rules are as follows:

As an example, the following statement results in a compile-time error:

while (false) { x=3; }

because the statement x=3; is not reachable; but the superficially similar case:

if (false) { x=3; }

does not result in a compile-time error. An optimizing compiler may realize that the statement x=3; will never be executed and may choose to omit the code for that statement from the generated class file, but the statement x=3; is not regarded as "unreachable" in the technical sense specified here.

The rationale for this differing treatment is to allow programmers to define "flag variables" such as:

static final boolean DEBUG = false;

and then write code such as:

if (DEBUG) { x=3; }

The idea is that it should be possible to change the value of DEBUG from false to true or from true to false and then compile the code correctly with no other changes to the program text.

This ability to "conditionally compile" has a significant impact on, and relationship to, binary compatibility (§13). If a set of classes that use such a "flag" variable are compiled and conditional code is omitted, it does not suffice later to distribute just a new version of the class or interface that contains the definition of the flag. A change to the value of a flag is, therefore, not binary compatible with preexisting binaries (§13.4.8). (There are other reasons for such incompatibility as well, such as the use of constants in case labels in switch statements; see §13.4.8.)

One ought not to be thrown into confusion
By a plain statement of relationship . . .
—Robert Frost, The Generations of Men (1914)