Scala:惯用的 Try-match 和避免捕获 Throwable

Scala: idiomatic Try-match and avoiding catching Throwable

在 Scala 中,模式匹配用于异常处理的典型用法(至少根据 this and this 等来源)如下所示:

Try(...) match {
  case Success(_) => println("success")
  case Failure(exc) => println(s"caught: $exc")
}

但是,该模式还捕获了 try 块中抛出的任何非 Exception Throwable

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 s(通常被认为是不可恢复的),需要额外的重新投掷,这似乎很奇怪,并且让这样的 Throwable s 转义,隐含在 Java-style try/catch 语法中,必须显式实现。

是否有更简洁/惯用的语法来在 Scala 中使用模式匹配进行异常处理,同时避免无意中捕获 Throwable

因为recover()方法接受一个PartialFunction,它可以用来过滤你想要处理的Throwable类型。之后,您可以让 get 展开 Try 并检索一个值,如果它是 Success 或已处理的 Failure,或者它将 re-throw 如果它仍然是 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