繁体   English   中英

类似的 Try 块在 scala 中尝试/最终块

[英]analogous Try block to try/finally block in scala

scala 的类似方式是什么Try

timer.start()
try {
  doThis()
} finally {
  timer.cancel()
}

鉴于Try中的异常只是创建了一个Failure值(与使用try时将控制权转移到外部 catch 块相反),原始finally块中的代码只需要在Try之后执行。 换句话说,这将:

timer.start()
val result = Try{
  doThis()
}
timer.cancel()
result

据我所知,没有内置的快捷方式可以避免捕获result以原样返回。

由于Try不会在您的程序流程中引发异常,我相信只需编写以下内容:

timer.start()
Try(doThis())
timer.cancel()

如果您希望处理异常(而不是盲目地忽略它)或调用结果,您可以将Try(doThis())分配给一个值并进一步处理它。

怎么样

Try {
  scala.util.control.Exception.ultimately {
    timer.cancel()
  } {
     doThis()
  }
}

?

尽管其他答案另有说明,但正确的答案是Try不能完全类似于传统的try...finally 这样做的原因是Try将忽略某些类型的异常,包括InterruptedExceptionControlThrowable等。

考虑是否按照其他答案的建议使用Try

lock.lock()
val t = Try(doStuff()) // Doesn't absorb all types of exceptions!
lock.unlock() // THIS MIGHT BE SKIPPED!!!
t.get

如果线程在doStuff()期间被中断,则会抛出InterruptedException ,并且Try将重新抛出它而不是创建Failure 这将导致lock.unlock()被跳过(你可能会死锁)。 如果doStuff()调用一个调用非本地返回的 lambda(它抛出ControlThrowable的子类型),也会发生同样的情况。

这可能是标准 Scala 库在Try类中不包含finally方法的原因——因为它不能正常工作。

不过,也有一些好消息。 Scala 2.13 引入了Using ,它本质上执行了一个 try-with-resources。 我们可以欺骗它做一个更一般的尝试......最后通过使用一个虚拟资源:

Using(lock.lock())(_ => doStuff())(_ => lock.unlock())

如果您在try之前没有任何惯用的操作,那么您可以在第一个参数列表中提供一个Unit

Using(())(_ => doStuff())(_ => lock.unlock())

但无论如何, Try不会完成这项工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM