Why does a Java Compiler not produce an unreachable statement error for an unreachable then statement?
The behaviour is defined in the JLS description of unreachable statements:
The then-statement is reachable iff the if-then statement is reachable.
So the compiler determines that the then-statement (break;
) is reachable, regardless of the condition in the if
.
And a bit further, emphasis mine:
A basic
for
statement can complete normally iff at least one of the following is true:
- The for statement is reachable, there is a condition expression, and the condition expression is not a constant expression (§15.28) with value true.
- There is a reachable
break
statement that exits the for statement.
So the for can complete normally because the then-statement contains a break
. As you noticed, it would not work if you replaced break
with return
.
The rationale is explained towards the end of the section. In substance, if
has a special treatment to allow constructs such as:
if(DEBUG) { ... }
where DEBUG may be a compile time constant.
As explained in my answer to a similar question, the specific construct if(compile-time-false)
is exempt from the unreachability rules as an explicit backdoor. In this case, the compiler treats your break
as reachable because of that.
From the JLS
An if-then statement can complete normally if 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.
So if(false)
is allowed.
This ability to "conditionally compile" has a significant impact on, and relationship to, binary compatibility. 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 . (There are other reasons for such incompatibility as well, such as the use of constants in case labels in switch statements;)