Scala:惯用的Try-match并避免抓到Throwable

sum*_*tsu 1 scala exception-handling throwable

在Scala中,模式匹配在异常处理中的典型用法(至少对于像thisthis这样的源而言)如下所示:

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

但是,该模式也可以捕获块中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
Run Code Online (Sandbox Code Playgroud)

至少在Java中,至少在Throwable没有令人信服的理由的情况下进行捕获通常被认为是一种反模式。(此消息源为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
}
Run Code Online (Sandbox Code Playgroud)

但是,似乎很奇怪,必须进行额外的重新抛出来避免捕获非Exception Throwables(通常认为是不可恢复的),并且必须明确实现Throwable以Java样式try/ catch语法隐含的这种逃逸。

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

jwv*_*wvh 6

由于该recover()方法采用PartialFunction,因此可以用于过滤Throwable要处理的类型。之后,您可以get解开Try并检索值(如果它是a Success或已处理)Failure,或者如果它仍然是a 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
Run Code Online (Sandbox Code Playgroud)