That's the way finally
works. The snippet
try {
throw new Exception();
} catch(Exception e) {
throw new Exception();
}
will complete abruptly, but the finally clause will kick in and when it returns it discards the original reason for completing the statement.
This is explained in section Blocks and Statements in the Java Language Specification. I've highlighted the relevant path in your situation:
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:
- 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
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
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).
- 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 execution of the
try
block completes
abruptly for any other reason
R, then the
finally
block is
executed. Then there is a choice: