tags:

views:

3167

answers:

5

I was surprised recently to find that it's possible to have a return statement in a finally block in Java.

It seems like lots of people think it's a bad thing to do as described in 'Don't return in a finally clause'. Scratching a little deaper, I also found 'Java's return doesn't always' which shows some pretty horrible examples of other types of flow control in finally blocks.

So, my question is, can anyone give me an example where a return statement (or other flow control) in a finally block produces better / more readable code?

+8  A: 

The examples you provided are reason enough to not use flow-control from finally.

Even if there's a contrived example where it's "better," consider the developer who has to maintain your code later and who might not be aware of the subtleties. That poor developer might even be you....

Jason Cohen
Sure. I guess I'm asking in case someone can give me some really compelling example on the side of good.
Matt Sheppard
+4  A: 

Adding control structures and returns to finally{} blocks are just another example of "just because you can" abuses which are scattered throughout virtually all development languages. Jason was right in suggesting it could easily become a maintenance nightmare - the arguments against early returns from functions apply more-so to this case of "late returns".

Finally blocks exist for one purpose, to allow you to completely tidy up after yourself, no matter what happened in all the preceeding code. Principally this is closing / releasing file pointers, database connections etc., though I could see it being stretched to say adding in bespoke auditing.

Anything that affects the return of the function should lie in the try{} block. Even if you had a method whereby you checked an external state, did a time consuming operation, then checked that state again in case it became invalid, you would still want the second check inside the try{} - if it sat inside finally{} and the long operation failed, you would then be checking that state a second time needlessly.

iAn
A: 

I can't think of any good use cases. You have to remember that Java was developed by programmers, not language theorists, so you can't really expect it to be wart-free.

Josh Segall
If Java was developed by programmers, we would have an unsigned byte.
Arafangion
+1  A: 

javac will warn of return in finally if you use the -Xlint:finally. Originally javac emitted no warnings - if something is wrong with the code, it should fail to compile. Unfortunately backwards compatibility means that unanticipated ingenious foolishness cannot be prohibited.

Exceptions can be thrown from finally blocks, but in that case the exhibited behaviour is almost certainly what you want.

Tom Hawtin - tackline
+4  A: 

I had a REALLY hard to track down bug years ago that was caused by this. The code was something like

Object problemMethod() {
  Object rtn = null;
  try {
     rtn = somethingThatThrewAnException();
  }
  finally {
     doSomeCleanup();
     return rtn;
  }
}

What happened is that the exception was thrown down in some other code. It was being caught and logged and rethrown within the somethingThatThrewAnException method. But the exception wasn't being propagated up past problemMethod. After a LONG time of looking at this we finally tracked it down to the return method. The return method in the finally block was basically stopping the exception that happened in the try block from propagating up even though it wasn't caught.

Like others have said, while it is legal to return from a finally block according to the Java spec, it is a BAD thing and shouldn't be done.

John Meagher