It's because you have a return
statement in your finally
block - so the IOException
is not actually going to be thrown out of your getCount()
method. If a finally
block completes abruptly (i.e. it throws an exception or has a return statement), that is the way that the whole try/finally or try/catch/finally block completes.
From JLS section 14.20.2:
If execution of the try block completes abruptly because of a throw of a value V, then there is a choice:
- ...
- 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).
And from section 11.2.2 (exception analysis of statements) - emphasis is mine:
A try statement (§14.20) can throw an exception class E iff either:
- The try block can throw E, or an expression used to initialize a resource (in a try-with-resources statement) can throw E, or the automatic invocation of the close() method of a resource (in a try-with-resources statement) can throw E, and E is not assignment compatible with any catchable exception class of any catch clause of the try statement, and either no finally block is present or the finally block can complete normally
- ...
In your case, the finally block cannot complete normally (i.e. get to the closing brace) due to the return statement, so the result of the analysis of the try statement is that it cannot throw the exception.
If you move the return 10;
to after the finally
block, you'll get the error you expected.