My question is; if the rest of the method has to continue then why do I not put the clean-up code after my try/catch block in a function.
Basically, like this:
InputStream is = ...
try {
// use stream
} catch (IOException ex) {
// report / recover
}
is.close();
But what happens if the // use stream
section throws a different (e.g. unchecked) exception? Or the // report / recover
code? In either case the close()
call doesn't happen. (And what if there is a break
or return
statement in those blocks?)
It is possible to implement it this way in theory. The problem is making sure that the code always (i.e. ALWAYS) runs. And it is difficult to do that without catching a whole bunch of exceptions that you shouldn't be catching ... and won't be able to deal with properly if you do catch.
All in all, finally
is the better solution.
- it is simpler than the convolutions you otherwise need to do to handle the situation properly, and
- it is more reliable than a typical half-hearted attempt.
And it is even simpler / more reliable if you can use the new Java 7 "try with resources" form in which the finally
is taken care of automatically.
I would add that your characterization of when the finally
clause is executed is a bit inaccurate. In reality, the finally
block is executed no matter how the try block terminates, including:
- when the
try
block drops off the end,
- when it throws an exception ... irrespective of whether the exception is caught at this level, or
- when it executes a
return
, continue
or break
.
In fact, the only cases where the finally
block does not execute are if the try
block calls System.exit()
or the JVM crashes. (Or if it goes into an infinite loop ...)