I stumbled upon code looking something like this:
void run() {
try {
doSomething();
} catch (Exception ex) {
System.out.println("Error: " + ex);
throw ex;
}
}
void doSomething() {
throw new RuntimeException();
}
This code surprises me because it looks like the run()
-method is capable of throwing an Exception
, since it catches Exception
and then rethrows it, but the method is not declared to throw Exception
and apparently doesn't need to be. This code compiles just fine (in Java 11 at least).
My expectation would be that I would have to declare throws Exception
in the run()
-method.
Extra information
In a similar way, if doSomething
is declared to throw IOException
then only IOException
needs to be declared in the run()
-method, even though Exception
is caught and rethrown.
void run() throws IOException {
try {
doSomething();
} catch (Exception ex) {
System.out.println("Error: " + ex);
throw ex;
}
}
void doSomething() throws IOException {
// ... whatever code you may want ...
}
Question
Java usually likes clarity, what is the reason behind this behavior? Has it always been like this? What in the Java Language Specification allows the run()
method not need to declare throws Exception
in the code snippets above? (If I would add it, IntelliJ warns me that Exception
is never thrown).
javac
- I've been running into cases where Eclipse compiler was more lenient. – Tailwind-source 1.6
flag raises a compilation error as expected. Compiling with source compatibility 7 does not raise the compilation error – HeliographIn detail, in Java SE 7 and later, when you declare one or more exception types in a catch clause, and rethrow the exception handled by this catch block, the compiler verifies that the type of the rethrown exception meets the following conditions : 1. 1. The try block is able to throw it. 2. There are no other preceding catch blocks that can handle it. 3. It is a subtype or supertype of one of the catch clause's exception parameters.
– Osmond