Scala:惯用尝试匹配并避免捕获Throwable

时间:2018-03-27 22:50:53

标签: scala exception-handling throwable

在Scala中,用于异常处理的模式匹配的典型用法(至少每个来源如thisthis)如下所示:

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

1 个答案:

答案 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