If I understand the question, you're asking what's the difference between:
try {
Foo f = new Foo();
f.bar();
}
finally
{
Foo.baz();
}
And:
// This doesn't actually compile because a try block needs a catch and/or finally block
try {
Foo f = new Foo();
f.bar();
}
Foo.baz();
Or, more likely:
Foo f = new Foo();
f.bar();
Foo.baz();
The difference is that if either new Foo()
or f.bar()
throw an exception, the finally
block will get executed in the first case, but that Foo.baz()
won't get executed in the last two cases: instead control will skip over Foo.baz()
while the JVM looks for an exception handler.
EDIT
Responding to your comment, what about:
Foo f = new Foo();
try {
f.bar();
}
catch (Exception ex)
{
// ...
}
f.baz();
You are right that, assuming the catch
block doesn't rethrow the exception, or return from the method indicating a failure occured, then f.baz()
gets called regardless of whether there was an exception. Even in that case, however, the finally
block serves as documentation that f.baz()
is used for cleanup.
More importantly, the fact that an exception was thrown usually is important, so it's very hard to write code that continues on doing whatever it was doing without knowing that an exception was thrown. There are times that exceptions indicate silly things that you can ignore, and in that case you should swallow the exception. More often, however, you will want to signal failure, either be rethrowing the exception (or throwing a different exception) or returning from the method with an error code.
For example, if f.bar()
is supposed to convert a String
to an Double
, and on failure it throws a NumberFormatException
, then code after the try
block probably needs to know that the String
was not actually converted to a Double
. And, so, in general you won't want to continue after the catch
block. Instead, you'll want to signal failure. This is known as "abort on failure" (compared to "resume on failure," which probably should be called "muddle on after failure with your fingers crossed").
Except in special cases you may be able to muddle on. For instance, the catch
block could set the relevant Double
to Double.NaN
which is designed specifically to propagate errors correctly in math expressions. Even in that case, the finally
block serves as documentation that f.baz()
is involved in some kind of cleanup.