unreachable statements
Sometimes, we will meet this compiler error: unreachable statements.
See the following examples:
public void javapapers() {
System.out.println("java");
return;
System.out.println("papers"); // compile error
}
public void javapapers() {
System.out.println("java");
if(true) {
return;
}
System.out.println("papers");
}
//This code compiled successfully
public void javapapers() {
System.out.println("java");
while(true) {
return;
}
System.out.println("papers"); // compile error
}
Wait, but what is strange here?
From Java Language Specification:
even though the value of
n
is known at compile time and in principle it can be known at compile time that the assignment tok
can never be executed.The rules in this section define two technical terms:
whether a statement is _reachable_
whether a statement _can complete normally_
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.”
A reachable
break
statement _exits a statement_ if, within the break target, either there are notry
statements whosetry
blocks contain thebreak
statement, or there aretry
statements whosetry
blocks contain thebreak
statement and allfinally
clauses of thosetry
statements can complete normally.This definition is based on the logic around “attempts to transfer control” in §14.15.
A
continue
statement _continues ado
statement_ if, within thedo
statement, either there are notry
statements whosetry
blocks contain thecontinue
statement, or there aretry
statements whosetry
blocks contain thecontinue
statement and allfinally
clauses of thosetry
statements can complete normally.The rules are as follows:
The block that is the body of a constructor, method, instance initializer, or static initializer is reachable.
An empty block that is not a switch block can complete normally iff it is reachable.
A non-empty block that is not a switch block can complete normally iff the last statement in it can complete normally.
The first statement in a non-empty block that is not a switch block is reachable iff the block is reachable.
Every other statement
S
in a non-empty block that is not a switch block is reachable iff the statement precedingS
can complete normally.
A local class declaration statement can complete normally iff it is reachable.
A local variable declaration statement can complete normally iff it is reachable.
An empty statement can complete normally iff it is reachable.
A labeled statement can complete normally if at least one of the following is true:
* <a name="jls-14.21-300-F-1"></a>The contained statement can complete normally. * <a name="jls-14.21-300-F-2"></a>There is a reachable `break` statement that exits the labeled statement.
The contained statement is reachable iff the labeled statement is reachable.
An expression statement can complete normally iff it is reachable.
An
if-then
statement can complete normally iff it is reachable.The
then
-statement is reachable iff theif-then
statement is reachable.An
if-then-else
statement can complete normally iff thethen
-statement can complete normally or theelse
-statement can complete normally.The
then
-statement is reachable iff theif-then-else
statement is reachable.The
else
-statement is reachable iff theif-then-else
statement is reachable.This handling of an
if
statement, whether or not it has anelse
part, is rather unusual. The rationale is given at the end of this section.
An
assert
statement can complete normally iff it is reachable.A
switch
statement can complete normally iff at least one of the following is true:* <a name="jls-14.21-300-J-1"></a>The switch block is empty or contains only switch labels. * <a name="jls-14.21-300-J-2"></a>The last statement in the switch block can complete normally. * <a name="jls-14.21-300-J-3"></a>There is at least one switch label after the last switch block statement group. * <a name="jls-14.21-300-J-4"></a>The switch block does not contain a `default` label. * <a name="jls-14.21-300-J-5"></a>There is a reachable `break` statement that exits the `switch` statement.
- A statement in a switch block is reachable iff its
switch
statement is reachable and at least one of the following is true:* <a name="jls-14.21-300-L-1"></a>It bears a `case` or `default` label. * <a name="jls-14.21-300-L-2"></a>There is a statement preceding it in the switch block and that preceding statement can complete normally.
* <a name="jls-14.21-300-M-1"></a>The `while` statement is reachable and the condition expression is not a constant expression ([§15.28](http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28 "15.28. Constant Expressions")) with value `true`. * <a name="jls-14.21-300-M-2"></a>There is a reachable `break` statement that exits the `while` statement.
The contained statement is reachable iff the
while
statement is reachable and the condition expression is not a constant expression whose value isfalse
.
- A
do
statement can complete normally iff at least one of the following is true:* <a name="jls-14.21-300-N-1"></a>The contained statement can complete normally and the condition expression is not a constant expression ([§15.28](http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28 "15.28. Constant Expressions")) with value`true`. * <a name="jls-14.21-300-N-2"></a>The `do` statement contains a reachable `continue` statement with no label, and the `do` statement is the innermost `while`, `do`, or `for`statement that contains that `continue` statement, and the `continue` statement continues that `do` statement, and the condition expression is not a constant expression with value `true`. * <a name="jls-14.21-300-N-3"></a>The `do` statement contains a reachable `continue` statement with a label `L`, and the `do` statement has label `L`, and the `continue`statement continues that `do` statement, and the condition expression is not a constant expression with value `true`. * <a name="jls-14.21-300-N-4"></a>There is a reachable `break` statement that exits the `do` statement.
The contained statement is reachable iff the
do
statement is reachable.
- A basic
for
statement can complete normally iff at least one of the following is true:* <a name="jls-14.21-300-O-1"></a>The `for` statement is reachable, there is a condition expression, and the condition expression is not a constant expression ([§15.28](http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28 "15.28. Constant Expressions")) with value `true`. * <a name="jls-14.21-300-O-2"></a>There is a reachable `break` statement that exits the `for` statement.
The contained statement is reachable iff the
for
statement is reachable and the condition expression is not a constant expression whose value isfalse
.
An enhanced
for
statement can complete normally iff it is reachable.A
break
,continue
,return
, orthrow
statement cannot complete normally.A
synchronized
statement can complete normally iff the contained statement can complete normally.The contained statement is reachable iff the
synchronized
statement is reachable.
- A
try
statement can complete normally iff both of the following are true:* <a name="jls-14.21-300-S-1"></a>The `try` block can complete normally or any `catch` block can complete normally. * <a name="jls-14.21-300-S-2"></a>If the `try` statement has a `finally` block, then the `finally` block can complete normally.
- A
catch
blockC
is reachable iff both of the following are true:* <a name="jls-14.21-300-U-1"></a>Either the type of `C`'s parameter is an unchecked exception type or `Throwable`; or some expression or `throw` statement in the `try`block is reachable and can throw a checked exception whose type is assignable to the parameter of the `catch` clause `C`. <a name="jls-14.21-300-U-1.1"></a>An expression is reachable iff the innermost statement containing it is reachable. See [§15.6](http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.6 "15.6. Normal and Abrupt Completion of Evaluation") for normal and abrupt completion of expressions. * <a name="jls-14.21-300-U-2"></a>There is no earlier `catch` block `A` in the `try` statement such that the type of `C`'s parameter is the same as or a subclass of the type of`A`'s parameter.
- If a
finally
block is present, it is reachable iff thetry
statement is reachable.One _might expect_ the
if
statement to be handled in the following manner:
- An
if-then
statement can complete normally iff at least one of the following is true:* The `if-then` statement is reachable and the condition expression is not a constant expression whose value is `true`. * The `then`-statement can complete normally.
The
then
-statement is reachable iff theif-then
statement is reachable and the condition expression is not a constant expression whose value isfalse
.
- An
if-then-else
statement can complete normally iff thethen
-statement can complete normally or theelse
-statement can complete normally.The
then
-statement is reachable iff theif-then-else
statement is reachable and the condition expression is not a constant expression whose value isfalse
.The
else
-statement is reachable iff theif-then-else
statement is reachable and the condition expression is not a constant expression whose value istrue
.This approach would be consistent with the treatment of other control structures. However, in order to allow the if statement to be used conveniently for “conditional compilation” purposes, the actual rules differ.
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:
>
> ``` java
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 generatedclass
file, but the statementx=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:
>
> ``` java
if (DEBUG) { x=3; }
>
>
The idea is that it should be possible to change the value of
DEBUG
fromfalse
totrue
or fromtrue
tofalse
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 pre-existing binaries (§13.4.9). (There are other reasons for such incompatibility as well, such as the use of constants in
case
labels inswitch
statements; see §13.4.9.)