finally块何时以及何时执行?

时间:2014-11-07 04:16:10

标签: scala jvm

考虑以下Scala代码(类似的代码示例适用于Java)

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

最后在返回"hello"后执行。但是什么时候它会被执行?它运行吗? 返回之后但在分配给a之前? (看起来像那样) 它是否在与赋值相同的线程中执行?

2 个答案:

答案 0 :(得分:1)

除了

  

System.exit()的

如果JVM由于某种原因崩溃(例如你的try块中的无限循环),则finally块将不会运行。

就线程本身而言,只有在使用 stop()方法停止时(或 suspend()而不使用 resume())将不执行finally块。对 interrupt()的调用仍然会导致finally块被执行。

还值得注意的是,由于finally块中的任何return语句都会覆盖try / catch块中的任何返回或异常抛出,如果发生这种情况,程序行为很快就会变得不稳定并且难以调试。没有什么值得采取预防措施(因为它只发生在非常罕见的情况下),但值得注意,以便在发生时能够识别它。

From this SO answer

答案 1 :(得分:1)

try块是一个表达式。 finally作为该表达式的评估的一部分运行。在赋值发生之前评估赋值右侧的表达式。由此我们得出结论,finally块作为评估的一部分,在作业发生之前运行。

是的,它在同一个线程中运行。我没有具体的参考,除了知道如果它没有这将是一个非常不幸的语言功能(并且反正很难实现)。

您使用"返回"令人困惑。什么都没有"返回&#34 ;;正在评估表达式,并将其结果值分配给某个东西。

关于表达式本身的详细信息,请参阅Scala language specification,第6.22节:

  

尝试表达......

try { b } finally e
     

...评估块b。如果   评估b不会导致抛出异常,表达式e   被评估。

     

如果在评估e期间抛出异常,则   对抛出的异常中止try表达式的评估。   如果在评估e期间未引发任何异常,则b的结果为。{1}}   作为try表达式的结果返回。如果是例外   在评估b期间抛出,还评估了finally块e。如果在评估e期间抛出另一个异常e,   对抛出的异常中止try表达式的评估。   如果在评估e期间没有抛出异常,则原始   b的评估完成后,e中抛出的异常将被重新抛出。   块b应符合预期的try类型   表达。最终表达式e应符合类型   Unit

     

尝试表达式:

try { b } catch e1 finally e2
     

的简写
try { try { b } catch e1 } finally e2

可在该部分找到更多细节。