Java 7 - Precise rethrow with a final Exception
In previous versions of java, rethrowing an exception was treated as throwing the type of the catch parameter.
For example:
public static void test() throws Exception{
DateFormat df = new SimpleDateFormat("yyyyMMdd");
try {
df.parse("x20110731");
new FileReader("file.txt").read();
} catch (Exception e) {
System.out.println("Caught exception: " + e.getMessage());
throw e;
}
}
In Java 7, you can be more precise about the exception being thrown, if you declare the exception final
:
//(doesn't compile in Java<7)
public static void test2() throws ParseException, IOException{
DateFormat df = new SimpleDateFormat("yyyyMMdd");
try {
df.parse("x20110731");
new FileReader("file.txt").read();
} catch (final Exception e) {
System.out.println("Caught exception: " + e.getMessage());
throw e;
}
}
My question: The docs say that I need to declare the Exception final
. But if I don't, the code above still compiles and works. Am I missing something?
References:
Project Coin开发者_如何学Go: multi-catch and final rethrow
Add more flexible checking for rethrown exceptionsI believe I saw a tweet from Josh Bloch saying that the "final" restriction had been lifted late on. I'll see if I can find a post about it, but I suspect it's just that any "early" documentation you read is now inaccurate.
EDIT: I can't find the exact "it's changed" post, but the Java 7 documentation states shows an example with it not being final. It talks about exception variables being implicitly final when a catch block declares more than one type, but that's slightly separate.
EDIT: I've now found the source of my confusion, but it's an internal mailing list post :( Anyway, it doesn't have to be declared as final, but I believe the compiler treats it as implicitly final - just like in the multi-catch scenario.
The reason why both compile is that an exception in a uni catch clause that is not subsequently modified is implicitly final (JLS 14.20).
So for your example not to compile, you need to modify e in some way, for example:
public static void test2() throws ParseException, IOException {
DateFormat df = new SimpleDateFormat("yyyyMMdd");
try {
df.parse("x20110731");
new FileReader("file.txt").read();
} catch (Exception e) {
if (e instanceof ParseException) {
e = new ParseException("Better message", 0);
} else {
e = new IOException("Better message");
}
System.out.println("Caught exception: " + e.getMessage());
throw e; //does not compile any more
}
}
Without the final it is still valid java. You just lose the benefit of it being 'precise'.
精彩评论