The Java programming language requires that a program contains handlers for checked exceptions which can result from execution of a method or constructor (§8.4.6, §8.8.5). This compile-time checking for the presence of exception handlers is designed to reduce the number of exceptions which are not properly handled. For each checked exception which is a possible result, the throws clause for the method or constructor must mention the class of that exception or one of the superclasses of the class of that exception (§11.2.3).
The checked exception classes (§11.1.1) named in the throws clause are part of the contract between the implementor and user of the method or constructor. The
throws clause of an overriding method may not specify that this method will result in throwing any checked exception which the overridden method is not permitted, by its throws clause, to throw (§8.4.8.3). When interfaces are involved, more than one method declaration may be overridden by a single overriding declaration. In this case, the overriding declaration must have a throws clause that is compatible with all the overridden declarations (§9.4.1).
The unchecked exception classes (§11.1.1) are exempted from compile-time checking.
Error classes are exempted because they can occur at many points in the program and recovery from them is difficult or impossible. A program declaring such exceptions would be cluttered, pointlessly. Sophisticated programs may yet wish to catch and attempt to recover from some of these conditions.
Run-time exception classes are exempted because, in the judgment of the designers of the Java programming language, having to declare such exceptions would not aid significantly in establishing the correctness of programs. Many of the operations and constructs of the Java programming language can result in exceptions at run time. The information available to a Java compiler, and the level of analysis a compiler performs, are usually not sufficient to establish that such run-time exceptions cannot occur, even though this may be obvious to the programmer. Requiring such exception classes to be declared would simply be an irritation to programmers.
For example, certain code might implement a circular data structure that, by construction, can never involve null references; the programmer can then be certain that a NullPointerException cannot occur, but it would be difficult for a Java compiler to prove it. The theorem-proving technology that is needed to establish such global properties of data structures is beyond the scope of this specification.
We say that a statement or expression can throw an exception class E if, according to the rules in §11.2.1 and §11.2.2, the execution of the statement or expression can result in an exception of class E being thrown.
11.2 Compile-Time Checking of Exceptions EXCEPTIONS
We say that a catch clause can catch its catchable exception class(es):
• The catchable exception class of a uni-catch clause is the declared type of its exception parameter (§14.20).
• The catchable exception classes of a multi-catch clause are the alternatives in the union that denotes the type of its exception parameter.
11.2.1 Exception Analysis of Expressions
A class instance creation expression (§15.9) can throw an exception class E iff either:
• The expression is a qualified class instance creation expression and the qualifying expression can throw E; or
• Some expression of the argument list can throw E; or
• E is one of the exception types of the invocation type of the chosen constructor (§15.12.2.6); or
• The class instance creation expression includes a ClassBody, and some instance initializer or instance variable initializer in the ClassBody can throw E.
A method invocation expression (§15.12) can throw an exception class E iff either:
• The method invocation expression is of the form Primary . [TypeArguments]
Identifier and the Primary expression can throw E; or
• Some expression of the argument list can throw E; or
• E is one of the exception types of the invocation type of the chosen method (§15.12.2.6).
A lambda expression (§15.27) can throw no exception classes.
For every other kind of expression, the expression can throw an exception class E
iff one of its immediate subexpressions can throw E.
Note that a method reference expression (§15.13) of the form Primary :: [TypeArguments]
Identifier can throw an exception class if the Primary subexpression can throw an exception class. In contrast, a lambda expression can throw nothing, and has no immediate subexpressions on which to perform exception analysis. It is the body of a lambda expression, containing expressions and statements, that can throw exception classes.
EXCEPTIONS Compile-Time Checking of Exceptions 11.2
11.2.2 Exception Analysis of Statements
A throw statement (§14.18) whose thrown expression has static type E and is not a final or effectively final exception parameter can throw E or any exception class that the thrown expression can throw.
For example, the statement throw new java.io.FileNotFoundException(); can throw java.io.FileNotFoundException only. Formally, it is not the case that it "can throw" a subclass or superclass of java.io.FileNotFoundException.
A throw statement whose thrown expression is a final or effectively final exception parameter of a catch 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; and
• E 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 same try statement.
A try statement (§14.20) can throw an exception class E iff either:
• The try block can throw E, or an expression used to initialize a resource (in a
try-with-resources statement) can throw E, or the automatic invocation of the
close() method of a resource (in a try-with-resources statement) can throw E, and E is not assignment compatible with any catchable exception class of any
catch clause of the try statement, and either no finally block is present or the
finally block can complete normally; or
• Some catch block of the try statement can throw E and either no finally block is present or the finally block can complete normally; or
• A finally block is present and can throw E.
An explicit constructor invocation statement (§8.8.7.1) can throw an exception class E iff either:
• Some expression of the constructor invocation's parameter list can throw E; or
• E is determined to be an exception class of the throws clause of the constructor that is invoked (§15.12.2.6).
Any other statement S can throw an exception class E iff an expression or statement immediately contained in S can throw E.
11.2 Compile-Time Checking of Exceptions EXCEPTIONS
11.2.3 Exception Checking
It is a compile-time error if a method or constructor body can throw some exception class E when E is a checked exception class and E is not a subclass of some class declared in the throws clause of the method or constructor.
It is a compile-time error if a lambda body can throw some exception class E when
E is a checked exception class and E is not a subclass of some class declared in the
throws clause of the function type targeted by the lambda expression.
It is a compile-time error if a class variable initializer (§8.3.2) or static initializer (§8.7) of a named class or interface can throw a checked exception class.
It is a compile-time error if an instance variable initializer (§8.3.2) or instance initializer (§8.6) of a named class can throw a checked exception class, unless the named class has at least one explicitly declared constructor and the exception class or one of its superclasses is explicitly declared in the throws clause of each constructor.
Note that no compile-time error is due if an instance variable initializer or instance initializer of an anonymous class (§15.9.5) can throw an exception class. In a named class, it is the responsibility of the programmer to propagate information about which exception classes can be thrown by initializers, by declaring a suitable throws clause on any explicit constructor declaration. This relationship between the checked exception classes thrown by a class's initializers and the checked exception classes declared by a class's constructors is assured for an anonymous class declaration, because no explicit constructor declarations are possible and a Java compiler always generates a constructor with a suitable throws clause for the anonymous class declaration based on the checked exception classes that its initializers can throw.
It is a compile-time error if a catch clause can catch checked exception class E1
and it is not the case that the try block corresponding to the catch clause can throw a checked exception class that is a subclass or superclass of E1, unless E1 is
Exception or a superclass of Exception.
It is a compile-time error if a catch clause can catch an exception class E1 and a preceding catch clause of the immediately enclosing try statement can catch E1
or a superclass of E1.
A Java compiler is encouraged to issue a warning if a catch clause can catch checked exception class E1 and the try block corresponding to the catch clause can throw checked exception class E2, where E2 <:E1, and a preceding catch clause of the immediately enclosing try statement can catch checked exception class E3, where E2<:E3<:E1. Example 11.2.3-1. Catching Checked Exceptions
import java.io.*;
EXCEPTIONS Compile-Time Checking of Exceptions 11.2
class StaticallyThrownExceptionsIncludeSubtypes { public static void main(String[] args) { try {
throw new FileNotFoundException();
} catch (IOException ioe) {
// "catch IOException" catches IOException // and any subtype.
} try {
throw new FileNotFoundException();
// Statement "can throw" FileNotFoundException.
// It is not the case that statement "can throw"
// a subtype or supertype of FileNotFoundException.
} catch (FileNotFoundException fnfe) { // ... Handle exception ...
} catch (IOException ioe) {
// Legal, but compilers are encouraged to give // warnings as of Java SE 7, because all subtypes of // IOException that the try block "can throw" have // already been caught by the prior catch clause.
} try { m();
// m's declaration says "throws IOException", so // m "can throw" IOException. It is not the case // that m "can throw" a subtype or supertype of // IOException (e.g. Exception).
} catch (FileNotFoundException fnfe) {
// Legal, because the dynamic type of the exception // might be FileNotFoundException.
} catch (IOException ioe) {
// Legal, because the dynamic type of the exception // might be a different subtype of IOException.
} catch (Throwable t) {
// Can always catch Throwable.
} }
static void m() throws IOException { throw new FileNotFoundException();
} }
By the rules above, each alternative in a multi-catch clause (§14.20) must be able to catch some exception class thrown by the try block and uncaught by previous catch clauses.
For example, the second catch clause below would cause a compile-time error because exception analysis determines that SubclassOfFoo is already caught by the first catch clause: