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: multi-catch and final rethrow
Add more flexible checking for rethrown exceptions
If a catch block cannot handle the particular exception it has caught, you can rethrow the exception. The rethrow expression ( throw without assignment_expression) causes the originally thrown object to be rethrown.
Final Rethow : Allows you to catch an exception type and it's subtype and rethrow it without having to add a throws clause to the method signature.
Java For TestersIf a catch block cannot handle the particular exception it has caught, we can rethrow the exception. The rethrow expression causes the originally thrown object to be rethrown.
If a catch block handles multiple exceptions, you can separate them using a pipe (|) and in this case, exception parameter (ex) is final, so you can't change it. The byte code generated by this feature is smaller and reduce code redundancy.
I 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 } }
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