Atomic Object’s blog on everything we find fascinating.

I've been a software developer at Atomic Object's Grand Rapids office since 2005. During that time I've been developing applications of all types (mobile, web, desktop, server-side) using a variety of languages and technologies. I love making software, learning new technologies, and being an Atom.

Return From a Finally Clause?

I recently discovered that you can put a return statement in a finally clause in Java and it will still compile. I also discovered that if there is a return statement in a finally clause, it will silently discard an exception if one is raised in the try.

Once again, in case that didn’t sink in — a seemingly harmless return in a finally clause will silently discard exceptions and return the specified value!

Now I can’t think of why one would put a return in a finally. And I was surprised to find out it is even allowed. This got me wondering if it’s something other languages allow, and if so what happens to exceptions in those languages?

Normal Usage

A finally clause is useful when there is something that needs to happen even in the case of an exception being raised. Closing some kind of I/O is probably one of the most common use cases:

In this example, it’s possible that the readInteger method of the Connection could raise a ConnectionException. I can’t do anything to handle the exception at this level so I need it to bubble up to the caller. But the Connection needs to be closed regardless, so putting it in the finally is perfect. Whether or not an exception is raised, the connection will always be closed. And if there is an exception, it will bubble up to the caller.

Java

The expected behavior of a finally block (or at least the behavior I expect) changes when you put a return statement inside of it. In this example (which I tested with Java 1.6) the thrown exception will not bubble out, and the method will return the integer 5.

1
2
3
4
5
6
7
8
9

publicint getNumber(){int result =0;try{
result =5;thrownewRuntimeException("No no no!");}finally{return result;}}

If the return result; statement is moved outside of the finally clause, the method raises a RuntimeException as I would expect.

JavaScript

It turns out that JavaScript has the exact same behavior — it silently discards exceptions when there is a return statement in a finally clause.

1
2
3
4
5
6
7
8
9

var getNumber =function(){var result =0;try{
result =5;throw"No no no!";}finally{return result;}};

Just like the Java example, this function will alway return the value 5.

Ruby

Surely Ruby doesn’t allow this confusing and error-prone syntax, right? Wrong. If you return from an ensure clause then an exception will be discarded, and a value will be returned.

1
2
3
4
5
6
7
8
9

def get_number
result = 0begin
result = 5raise"No no no!"ensurereturn result
endend

As before, the result of calling this method is going to be 5. The idiom in Ruby is to not use the return statement at all in most cases, so this isn’t likely to affect anyone, but I still found it interesting that it was allowed and had the same results as Java and JavaScript.

C#

Finally some sanity. A C# program will not compile if there is a return in a finally. I did not try this myself, but according to this StackOverflow answer, you will get this compiler error if it is attempted:

Control cannot leave the body of a finally clause

Conclusion

Return statements don’t belong in finally clauses. Surprisingly, to me at least, a number of languages allow this syntax and the non-obvious and nasty side-effect it has of discarding exceptions. A try/finally (or a begin/ensure) can be just what is needed to make sure some code is executed before a method exits – just watch where you put your return.

1 Comment

While 99% of the time that will just lead to subtle bugs in error-handling code, having the choice to explicitly return a different value after (and possibly derived from) cleanup code can be useful. It’s a step in the direction of error handling patterns like restartable exceptions, as used in Common Lisp, Smalltalk, and probably some other languages. Unfortunately, the call stack has already been unwound in the languages you list (I think), so there is less information to go on when handling the exception.

You can do roughly the same thing in Lua before the call stack is unwound, but it needs to be explicitly requested with xpcall, so it shouldn’t lead to surprises.