if(false) vs. while(false): unreachable code vs. dead code
The JLS section on unreachable code explains the rationale. Essentially, Java normally shouldn't use conditional compilation like C routinely does with #ifdef
, but there are some situations (such as debugging, and in particular backward binary compatibility) where allowing the compiler to entirely strip out code is needed, and so the specific construct if(false)
is permitted for that purpose.
Why is an if/else if/else for a simple boolean not giving an unreachable code error
From JLS 14.21. Unreachable Statements
It is a compile-time error if a statement cannot be executed because it is unreachable.
and
The else-statement is reachable iff the if-then-else statement is reachable.
Your if-then-else statement is reachable. So, by the definition the compiler thinks that the else-statement is reachable.
Note: Interestingly the following code also compiles
// This is ok
if (false) { /* do something */ }
This is not true for while
// This will not compile
while (false) { /* do something */ }
because the reachability definition for while
is different (emphasis mine):
The contained statement is reachable iff the while statement is reachable and the condition expression is not a constant expression whose value is false.
Unreachable statement: while true vs if true
There are quite strict rules when statements are reachable in java. These rules are design to be easily evaluated and not to be 100% acurate. It should prevent basic programming errors. To reason about reachability in java you are restricted to these rules, "common logic" does not apply.
So here are the rules from the Java Language Specification 14.21. Unreachable Statements
An if-then statement can complete normally iff it is reachable.
So without an else, statements after an if-then are always reachable
A while statement can complete normally iff at least one of the following is true:
The while statement is reachable and the condition expression is not a constant expression (§15.28) with value true.
There is a reachable break statement that exits the while statement.
The condition is a constant expression "true", there is no break. Hence it does not complete normally.
Why Java identifies unreachable code only in case of while loop?
As described in Java Language Specification, this feature is reserved for "conditional compilation".
An example, described in the JLS, is that you may have a constant
static final boolean DEBUG = false;
and the code that uses this constant
if (DEBUG) { x=3; }
The idea is to provide a possibility to change DEBUG
from true
to false
easily without making any other changes to the code, which would not be possible if the above code gave a compilation error.
Why isn't unreachable code detected when an if condition is a constant?
From the Java Language Specification, 14.21. Unreachable Statements (emphasis by me):
It is a compile-time error if a statement cannot be executed because
it is unreachable.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, instance
initializer, 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 ofwhile
,do
, andfor
statements whose condition expression has the constant value true, the
values of expressions are not taken into account in the flow analysis.
So while the code is indeed unreachable, the compiler explicitly does not regard it as such. The reason stated is to allow programmers to define "flag" variables such as
static final boolean DEBUG = false;
if (DEBUG) { x=3; }
It should be possible to switch DEBUG
between false
and true
without having to change anything else in the code (due to compilation errors).
Unreachable code error vs. dead code warning in Java under Eclipse?
The first does not compile (you got an error), the second compiles (you just got a warning). That's the difference.
As to why Eclipse detects dead code, well, that's just the convenience of an integrated development tool with a built-in compiler which can be finetuned more as opposed to JDK to detect this kind of code.
Update: the JDK actually eliminates dead code.
public class Test {
public void foo() {
System.out.println("foo");
if(true)return;
System.out.println("foo");
}
public void bar() {
System.out.println("bar");
if(false)return;
System.out.println("bar");
}
}
javap -c
says:
public class Test extends java.lang.Object{
public Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: return
public void foo();
Code:
0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3; //String foo
5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/StrV
8: return
public void bar();
Code:
0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #5; //String bar
5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
11: ldc #5; //String bar
13: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
16: return
}
As to why it (Sun) doesn't give a warning about that, I have no idea :) At least the JDK compiler has actually DCE (Dead Code Elimination) builtin.
if(false) vs. while(false): unreachable code vs. dead code
The JLS section on unreachable code explains the rationale. Essentially, Java normally shouldn't use conditional compilation like C routinely does with #ifdef
, but there are some situations (such as debugging, and in particular backward binary compatibility) where allowing the compiler to entirely strip out code is needed, and so the specific construct if(false)
is permitted for that purpose.
Obvious false condition in else if, not giving dead code for body inside
The JLS has a definition of unreachable code:
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.
So this is not considered "unreachable".
Also see this discussion about unreachable code errors and dead code warnings.
Related Topics
What's the Difference Between Instance Method Reference Types in Java 8
How to Copy File Inside Jar to Outside the Jar
Modifying Local Variable from Inside Lambda
How to Write an Arraylist of Strings into a Text File
What Is the Regex for "Any Positive Integer, Excluding 0"
Session.Connection() Deprecated on Hibernate
When to Use Atomicreference in Java
Using Javafx in Jre 8, "Access Restriction" Error
Exception in Initializer Error in Java When Using Netbeans
How to Bundle Images in Jar File
Httpservletrequest - Setcharacterencoding Seems to Do Nothing
Mocking Files in Java - Mock Contents - Mockito
Preparedstatement with Statement.Return_Generated_Keys
How to Check for a Valid Url in Java
Why Is "Final" Not Allowed in Java 8 Interface Methods
Differences Between Java 8 Date Time API (Java.Time) and Joda-Time