Reputation: 1982
Java allows me to compile the following code without any issues:
public class Test {
public static void main(String[] args){
try {
throw new RuntimeException();
} catch (Exception e) {
throw e;
}
}
}
Even though java.lang.Exception is a checked exception. Meaning that I am rethrowing unchecked exception as checked and get away with that.
Most likely Java compiler is able to figure out that no checked exception is thrown in the try block, but I can't find the section in the specification that backups that.
Can one rely on this behavior and starting from which JDK version?
Update: This class doesn't compile with Java 1.6.0_38 with the following message:
Test.java:6: unreported exception java.lang.Exception; must be caught or declared to be thrown
throw e;
^
1 error
Upvotes: 2
Views: 526
Reputation: 719426
The part of the Java Language Specification that governs this can be found in JLS 11.2.2
11.2.2. Exception Analysis of Statements
...
A
throw
statement whose thrown expression is a final or effectively final exception parameter of acatch
clause C can throw an exception class E iff:
E is an exception class that the try block of the
try
statement which declares C can throw; andE is assignment compatible with any of C's catchable exception classes; and
E is not assignment compatible with any of the catchable exception classes of the
catch
clauses declared to the left of C in the sametry
statement.
When E is RuntimeException
1) E can be thrown in the try block, 2) the catch clause can catch it, and 3) there are no catch clauses "to the left". Therefore the throw
in the catch clause can throw RuntimeException
.
On the other hand, E is Exception
, E cannot be thrown in the try block. Therefore the throw
in the catch clause cannot throw Exception
.
Upvotes: 0
Reputation: 1982
It looks like that this is one of the effects of the enhancement in Java 7: Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking. See section "Rethrowing Exceptions with More Inclusive Type Checking."
The Java SE 7 compiler can determine that the exception thrown by the statement throw e must have come from the try block, and the only exceptions thrown by the try block can be FirstException and SecondException. Even though the exception parameter of the catch clause, e, is type Exception, the compiler can determine that it is an instance of either FirstException or SecondException.
Please note, that the following will not compile though even in Java 7 and above:
public class Test {
public static void main(String[] args){
try {
throw new RuntimeException();
} catch (Exception e) {
Exception e1 = e;
throw e1;
}
}
}
Because:
This analysis is disabled if the catch parameter is assigned to another value in the catch block.
Upvotes: 2