Look at the following infinite while
loop in Java. It causes a compile-time error for the statement below it.
while(true) {
System.out.println("inside while");
}
System.out.println("while terminated"); //Unreachable statement - compiler-error.
The following same infinite while
loop, however works fine and doesn't issue any errors in which I just replaced the condition with a boolean variable.
boolean b=true;
while(b) {
System.out.println("inside while");
}
System.out.println("while terminated"); //No error here.
In the second case also, the statement after the loop is obviously unreachable because the boolean variable b
is true still the compiler doesn't complain at all. Why?
Edit : The following version of while
gets stuck into an infinite loop as obvious but issues no compiler errors for the statement below it even though the if
condition within the loop is always false
and consequently, the loop can never return and can be determined by the compiler at the compile-time itself.
while(true) {
if(false) {
break;
}
System.out.println("inside while");
}
System.out.println("while terminated"); //No error here.
while(true) {
if(false) { //if true then also
return; //Replacing return with break fixes the following error.
}
System.out.println("inside while");
}
System.out.println("while terminated"); //Compiler-error - unreachable statement.
while(true) {
if(true) {
System.out.println("inside if");
return;
}
System.out.println("inside while"); //No error here.
}
System.out.println("while terminated"); //Compiler-error - unreachable statement.
Edit : Same thing with if
and while
.
if(false) {
System.out.println("inside if"); //No error here.
}
while(false) {
System.out.println("inside while");
// Compiler's complain - unreachable statement.
}
while(true) {
if(true) {
System.out.println("inside if");
break;
}
System.out.println("inside while"); //No error here.
}
The following version of while
also gets stuck into an infinite loop.
while(true) {
try {
System.out.println("inside while");
return; //Replacing return with break makes no difference here.
} finally {
continue;
}
}
This is because the finally
block is always executed even though the return
statement encounters before it within the try
block itself.
The first Statement always result in an infinite loop because we have specify a constant in condition of while loop, where as in second case compiler assume that, there is possibility of change of value of b inside loop.
If the compiler can conclusively determine that the boolean will evaluate to
true
at run-time, it will throw that error. The compiler assumes that the variable you declared can be changed (albeit we know here as humans it will not).To emphasize this fact, if variables are declared as
final
in Java, most compilers will throw the same error as if you substituted for the value. This is because the variable is defined at compile time (and cannot be changed at run-time) and the compiler can therefore conclusively determine that the expression evaluates totrue
at run-time.According the specifications, the following is said about while statements.
So, the compiler will only say that the code following a while statement is unreachable if the while condition is a constant with a true value, or there is a break statement within the while. In the second case, since the value of b is not a constant, it doesn't consider the code following it to be unreachable. There's a whole lot more information behind that link to give you more details on just what is and what isn't considered unreachable.
Because analyzing variable state is hard, so the compiler has pretty much just given up and let you do what you wish. Additionally, the Java Language Specification has clear rules about how the compiler is allowed to detect unreachable code.
There are many ways to trick the compiler - another common example is
which wouldn't work, as the compiler would realize that the area was unreacable. Instead, you could do
This would work since the compiler is unable to realize that the expression will never be false.
My guess is the variable "b" has possibility to change its value, so compiler think
System.out.println("while terminated");
can be reached.From the compiler's perspective the
b
inwhile(b)
could change to false somewhere. The compiler just doesn't bother checking.For fun try
while(1 < 2)
,for(int i = 0; i < 1; i--)
etc.