3

Consider the following Scala code (similar code examples work for Java)

val a = try "hello" catch { 
  case e:Exception => throw new Exception("from catch")
} finally println("done")

Finally executes after "hello" is returned. But when exactly does it get executed? Does it run after the return but before it is assigned to a? (it seems like that) Does it execute in the same thread as the assignment?

Jason C
  • 38,729
  • 14
  • 126
  • 182
Jus12
  • 17,824
  • 28
  • 99
  • 157

2 Answers2

2

Besides a

System.exit()

the finally block will not run if the JVM crashes for some reason (e.g. infinite loop in your try block).

As far as the thread itself, only if it is stopped using the stop() method (or suspend() without resume()) will the finally block not be executed. A call to interrupt() will still result in the finally block being executed.

It's also worth noting that, since any return statement in the finally block will override any returns or exception throws in the try/catch blocks, program behavior can quickly become erratic and hard to debug if this happens to you. Not really anything worth taking precaution against (as it only happens in extremely rare cases), but worth being aware of so you can recognize it when it happens.

From this SO answer

Community
  • 1
  • 1
Krishna
  • 170
  • 8
2

A try block is an expression. The finally runs as part of the evaluation of that expression. The expression on the right-hand side of an assignment is evaluated before the assignment takes place. From this we conclude that the finally block, as part of that evaluation, runs before the assignment takes place.

Yes, it runs in the same thread. I have no concrete reference for that other than knowing that it would be a very unfortunate language feature if it did not (and rather difficult to implement anyways).

Your use of the word "returned" is confusing. Nothing is being "returned"; an expression is being evaluated and its resulting value is being assigned to something.

As for the details of the expression itself, from the Scala language specification, section 6.22:

A try expression ...

try { b } finally e

... evaluates the block b. If evaluation of b does not cause an exception to be thrown, the expression e is evaluated.

If an exception is thrown during evaluation of e, the evaluation of the try expression is aborted with the thrown exception. If no exception is thrown during evaluation of e, the result of b is returned as the result of the try expression. If an exception is thrown during evaluation of b, the finally block e is also evaluated. If another exception e is thrown during evaluation of e, evaluation of the try expression is aborted with the thrown exception. If no exception is thrown during evaluation of e, the original exception thrown in b is re-thrown once evaluation of e has completed. The block b is expected to conform to the expected type of the try expression. The finally expression e is expected to conform to type Unit.

A try expression:

try { b } catch e1 finally e2

is a shorthand for

try { try { b } catch e1 } finally e2

Further details can be found in that section.

Jason C
  • 38,729
  • 14
  • 126
  • 182