Hello everyone, I'm studying the final chapter of Mala Gupta's book and I'm doing some simulation with the exceptions. In particular, I focused on the phrase:
"a finally block alone wouldn't suffice if code in the try block throws a checked exception. In this case you need to catch the checked exception or declare it to be thrown by your method. Otherwise your code won't compile."
And I've tested it with a simple example:
but....I can't understand why declaring the method with a return value there is no compilation error and it seems that I don't have to catch the checked exception:
You can make your first code snippet compile as well by simpling adding return; in the finally block. And it only helps to add the return statement in the finally block, if you add it after the finally block you get 2 compiler errors. So it seems that the return statement is responsible for making this code compile although the code doesn't meet the handle-or-declare rule for checked exceptions.
My IDE gives me this warning after adding the return in the finally block: finally block does not complete normally. That's why I was unaware of this behavior, a good java developer doesn't use return in a finally block Although it's possible (and allowed by the compiler) it's strongly discouraged to use control flow (return, continue,...) in finally blocks. It's really B-A-D! What happens if you do (and what you see in your code experiments) is well explained in this blog article.
Thank you so much for the help. Now I understand where the problem lies. Unfortunately I am not a java programmer, I was just trying out the various rules written in the Mala Gupta's book. She has done two examples of what happens when you change the value returned by the catch block in the finally block ..... I used the same piece of code to check that the compiler signaled the unhandled exception .... otherwise I would not even noticed this particular case.
Ah! After spending half-an-hour in JLS and JVM Spec, I finally found the reason there in JLS Section 14.20.2 , specifically these lines:
If execution of the try block completes abruptly because of a throw of a value V, then there is a choice:
If the run-time type of V is not assignment compatible with a catchable exception class of any catch clause of the try statement, then the finally block is executed. Then there is a choice:
If the finally block completes normally, then the try statement completes abruptly because of a throw of the value V.
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and the throw of value V is discarded and forgotten).
It can be seen, then, that a return statement always completes abruptly.
So, the second rule in the above list is applicable here. Since finally block completes abruptly due to a return statement (Reason S), the try statement completes abruptly because of that return statement. And hence your method returns 0.
Lesson of the day: You should never ever return from a finally block, else be ready for surprises