Roedy Green said:
Here's one reason from JLS 2.0 §14.16:
"...if there are any try statements (§14.19) within the method or
constructor whose try blocks contain the return statement, then any finally
clauses of those try statements will be executed, in order, innermost to
outermost, before control is transferred to the invoker of the method or
constructor. Abrupt completion of a finally clause can disrupt the transfer
of control initiated by a return statement."
There's also this in §14.19.2 (more readable in the JLS itself):
"A try statement with a finally block is executed by first executing the try
block. Then there is a choice:
* If execution of the try block completes normally, then the finally
block
is executed, and then there is a choice:
o If the finally block completes normally, then the try statement
completes normally.
o If the finally block completes abruptly for reason S, then the
try
statement completes abruptly for reason S.
* If execution of the try block completes abruptly because of a throw of
a
value V, then there is a choice:
o If the run-time type of V is assignable to the parameter of any
catch clause of the try statement, then the first (leftmost)
such
catch clause is selected. The value V is assigned to the
parameter
of the selected catch clause, and the Block of that catch clause
is
executed. Then there is a choice:
+ If the catch block completes normally, then the finally
block
is executed. Then there is a choice:
# If the finally block completes normally, then the
try
statement completes normally.
# If the finally block completes abruptly for any
reason,
then the try statement completes abruptly for the
same
reason.
+ If the catch block completes abruptly for reason R, then
the
finally block is executed. Then there is a choice:
# If the finally block completes normally, then the
try
statement completes abruptly for reason R.
# If the finally block completes abruptly for reason
S,
then the try statement completes abruptly for reason
S
(and reason R is discarded).
o If the run-time type of V is not assignable to the parameter 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).
* If execution of the try block completes abruptly for any other reason
R,
then the finally block is executed. Then there is a choice:
o If the finally block completes normally, then the try statement
completes abruptly for reason R.
o If the finally block completes abruptly for reason S, then the
try
statement completes abruptly for reason S (and reason R is
discarded)."
If you consider the implications of the last "*" point there, you'll see
that there could be some unusual effects of returning, throwing, and other
things from a finally block.