Java 7’s Final Rethrow Capability: It’s Effect on Method Signatures

So I’ve recently started re-reading a book called “The Well Grounded Java Developer”, that I started reading a couple of years ago. Granted, Java 7 isn’t the latest and greatest Java version, but IMO, I would do well to learn Java 7 in detail, as well as complementary JVM languages like Groovy, Clojure, and Scala. Of course, I would also do well to learn Java 8 and 9 in depth as well. One the early sections in the Well Grounded Java Developer – Sec. 1.3, The Changes in Project Coin, describes the new Final Rethrow capability of the Java compiler. When I first read about this functionality, I was confused about it, so I’m writing a brief post to succinctly explain what it is and its effect on method signatures in Java 7.

In Java 6, methods signatures were required to throw the types of all caught exceptions (that aren’t runtime exceptions) as defined by the catch blocks. For example, consider the following code:

[code language=”java”]
public void testTypicalRethrow() throws Exception {
try {
throwSqlException();
throwIoException();
} catch (Exception e) {
throw e;
}
}

private void throwSqlException() throws SQLException {
throw new SQLException();
}

private void throwIoException() throws IOException {
throw new IOException();
}
[/code]

In the above code, we want a generic catch block (because we want to just rethrow the SQLException and the IOException). We also want a precise method signature (i.e. testTypicalRethrow() throws IOException, SQLException), but Java 6 forces us to throw an Exception, not either an IOException or a SQLException. So, in Java 6, the following line (in the context of the above code) would result in a compiler error.

public void testTypicalRethrow() throws IOException, SQLException {

However, the Java 7 compiler is smarter. The above line is now legal. Now, the following code is legal:
[code language=”java”]
public void testTypicalRethrow() throws IOException, SQLException {
try {
throwSqlException();
throwIoException();
} catch (Exception e) {
throw e;
}
}
[/code]
Previously, this signature of testTypicalRethrow would be illegal, but because the increased compiler intelligence brought on by the Final Rethrow feature allows this code to now be compiled, our method signatures can be more precise, while also having generic catch blocks.

The Final Rethrow capability allows the method signature to throw all possible types of exceptions that are actually caught, without relying of the catch blocks, themselves.

One last point… Ironically, the final keyword isn’t actually required, as you can see from the code above. So long as the original caught exception is rethrown, the compiler is intelligent enough to allow for the more restrictive method signature.

Happy coding.