Unreachable code working fine – How?

  • A+
Category:Languages

From my understanding following code that I have wrote should not compile as the statement "I am unreachable" is after return.

However, It is compiling absolutely fine.

Also from JLS:Unreachable Statements it should not compile.

from the spec, at 14.21 Unreachable Statements:

A try statement can complete normally if both of the following are true:

  • The try block can complete normally or any catch block can complete normally.

  • If the try statement has a finally block, then the finally block can complete normally.

here the try block can't complete normally but the catch block can as well as the finally block, so I am confused here

    public class Test1 {      public static void main(String[] args) {         try {             return;          } catch (Exception e) {             System.out.println("catch");          } finally {             System.out.println("finally");         }         System.out.println("I am unreachable??!!!");     } } 

Can some one help me understand this behavior.

 


I believe these are the relevant quotes from JLS 14.21:

  • 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 preceding S can complete normally.

So your

System.out.println("I am unreachable??!!!"); 

statement is reachable iff (that means "if and only if") the try statement can complete normally, which leads to the next quote:

  • A try statement can complete normally iff both of the following are true:

    • The try block can complete normally or any catch block can complete normally.

    • If the try statement has a finally block, then the finally block can complete normally.

Since your catch block can complete normally and you have a finally block that can complete normally, the try statement can complete normally. Hence the System.out.println("I am unreachable??!!!"); statement following it is deemed reachable, regardless of the return; statement inside the try block.

Note the or in

The try block can complete normally or any catch block can complete normally.

This requires either the try block or at least one of the catch blocks to complete normally. It doesn't require both the try block and catch block to complete normally.

Finally, the logic behind this behavior:

The compiler is not supposed to analyze whether a try block can or cannot throw an Exception. The reason is that the Exception class hierarchy includes both checked and unchecked exceptions, and unchecked exceptions are not declared in throws clauses (if you replaced Exception with some checked exception, such as IOException, the compiler would complain that your try block never throws that exception, which would make the catch block unreachable).

Therefore, since you have a catch (Exception e) block which can complete normally, the compiler assumes that this catch block it reachable, and therefore the entire try statement can complete normally, even though the try block cannot complete normally.

The finally block, if present, must also be able to complete normally, since the finally block is also executed, so if it couldn't complete normally, the entire try statement couldn't complete normally.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: