Engineering Full Stack Apps with Java and JavaScript
It is a compile-time error if a statement cannot be executed because it is unreachable. There are many rules, but we will consider few important ones here.
The idea of reachable 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.
For example, below code won’t compile as the condition is a constant and the code inside will never be reached:
while(false){
//some code
}
Similarly, the below code will also not compile:
final boolean boolFalse = false;
while(boolFalse) {
//some code
}
However if you remove the final modifier of boolFalse, the above code will compile. This is because boolFalse will no longer be a constant and its value might be changed from within the code. Even though no one is actually changing it, it will still compile.
The ‘if’ is an exception to the above rules and hence it will always compile. For example below code will compile.
if(false){
//some code
}
The rationale for this differing treatment is to allow programmers to define "flag variables" such as:
static final boolean DEBUG = false;
if (DEBUG) { //some code
}
The current values of expressions are not taken into account in the flow analysis, if the expressions are not constants. Below code will compile even though the code inside while is never executed with i=3:
int i=3;
while(i>5){//some code
}
System.out.println("AFTER WHILE");
If we make I as final, the above code won,t compile as 3 is not greater than 5. If we assign I with 7 instead of 3, while block will compile, but the next line (System.out.println("AFTER WHILE");) won’t compile as while will go into an infinite loop and next line won’t be reached.
The block that is the body of a constructor, method, instance initializer, or static initializer is reachable. A non-empty block that is not a switch block can complete normally iff the last statement in it can complete normally. A statement can complete normally only if it is reachable. If we make i as final and place it in a instance initialize as below, it won’t compile and give an error that “Initializer does not complete normally” in addition to Unreachable code”:
{
int i=3;
while(i>5){//some code
}
System.out.println("AFTER WHILE"); }
Let us consider some examples:
Example-1: Will the below blocks of code compile?
Block 1
while (false) { x=3; }
Block 2
if (false) { x=3; }
Both blocks are unreachable and compiler in general won’t compile with unreachable code. However Block 2 will compile, but not Block 1 as if is treated differently.
Example-2:
public static void main(String[] args) {
final boolean boolFalse = false;
final boolean boolTrue = true;
//Block 1
if(boolFalse){
System.out.println("FALSE"); }
//Block 2
while(boolFalse) {
System.out.println("FALSE"); }
//Block 3
while(boolTrue) {
System.out.println("FALSE"); }
//Block 4
if(boolTrue){
System.out.println("FALSE"); }
}
Block1 and Block3 will only compile. Here Block1 will compile as if is treated differently for unreachable code. Block2 will not compile as it is unreachable code. Block3 will compile as it is reachable. However Block4 won’t compile as Block3 will run in an infinite loop.
Example-3:
public static void main(String[] args) {
boolean boolFalse = false;
boolean boolTrue = true;
//Block 1
if(boolFalse){
System.out.println("FALSE"); }
//Block 2
while(boolFalse) {
System.out.println("FALSE"); }
//Block 3
while(boolTrue) {
System.out.println("FALSE"); }
//Block 4
if(boolTrue){
System.out.println("FALSE"); }
}
Here all code blocks will compile as the variables boolFalse and boolTrue are not constants.
For the complete rules, you can refer JLS 14.21. JLS stands for Java Language Specification.