在Scala中,用于异常处理的模式匹配的典型用法(至少每个来源如this和this)如下所示:
Try(...) match {
case Success(_) => println("success")
case Failure(exc) => println(s"caught: $exc")
}
但是,该模式还会捕获Exception
块中抛出的所有非Throwable
try
:
Try(throw new AssertionError("assertion error")) match {
case Success(_) => println("success")
case Failure(exc) => println(s"caught: $exc")
}
caught: java.lang.AssertionError: assertion error
至少在Java中,在没有令人信服的理由的情况下捕获Throwable
通常被认为是一种反模式。 (This source为Scala提供了同样的建议。)
避免无声捕捉Throwable
的一个选择是抓住它并重新抛出它:
Try(throw new AssertionError("assertion error")) match {
case Success(_) => println("success")
case Failure(exc : Exception) => println(s"caught: $exc")
case Failure(th) => throw th
}
但是,为了避免捕获非Exception
Throwable
(通常被认为是不可恢复的)并且允许这样的Throwable
逃脱,有必要额外重新抛出,这似乎很奇怪。 ,隐式的Java风格的try
/ catch
语法必须明确实现。
在Scala中使用模式匹配进行异常处理是否有更简洁/惯用的语法,同时避免无意中捕获Throwable
?
答案 0 :(得分:5)
由于recover()
方法需要PartialFunction,因此可以使用它来过滤您要处理的Throwable
类型。之后,您可以让get
解包Try
并检索一个值,如果它是Success
或已处理的Failure
,或者如果它仍然是,它会重新抛出一个Failure
,即不由recover()
处理。
val result = Try{
//code block here
}.recover{
case exc:Exception => ... //should return same type as Success
}.get //unwrap the Try, will throw if Throwable was not an Exception