I am compiling this class:
public class Test {
// No throws clause here
public static void main(String[] args) {
doThrow(new SQLException());
}
static void doThrow(Exception e) {
Test.<Exception>doThrow0(e);
Test.doThrow0(e);
}
static <E extends Exception> void doThrow0(Exception e) throws E {
throw (E) e;
}
}
Why **Test.<Exception>doThrow0(e);** this line gives error to specify throws clause (or enclose it in try-catch )
And **Test.doThrow0(e);** this line don't give any error to use throws clause
This is because type inference prefers inferring type parameters that appear in the throws clause to unchecked exceptions whenever possible.
From JLS 18.1.3:
During the inference process, a set of bounds on inference variables is maintained. A bound has one of the following forms:
- ...
throws α: The inference variable α appears in athrowsclause....
A bound of the form
throws αis purely informational: it directs resolution to optimize the instantiation of α so that, if possible, it is not a checked exception type.
In the first attempt to resolution, this bound is taken into account.
Otherwise, if the bound set contains
throws αi, and each proper upper bound of αi is a supertype ofRuntimeException, then Ti =RuntimeException.
In Test.doThrow0(e), there is nothing suggesting that E should be a checked exception, so type inference infers it to be RuntimeException, an unchecked exception.
If doThrow0 took an E as parameter instead, that establishes a relationship between the type of the argument and the type of the exception doThrow0 throws. Now E would be inferred to be Exception in the call Test.doThrow0(e).
In Test<Exception>doThrow0(e), you explicitly specified that E should be a checked exception. Type inference doesn't even get involved here.
See also this other question where you can find examples where this "try not to infer a checked exception" is desirable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With