即使在Scala中捕获异常后也执行代码块

时间:2014-12-11 22:57:55

标签: scala exception-handling

在我当前的方法中,我试图进行一系列调用,如果其中任何一个失败,我希望能够继续运行其余部分(同时捕获抛出的异常)。我很难在Scala中搞清楚这一点。

所以在这个例子中,我想开始这些调用 - RunA,RunB和RunC但是如果RunB抛出异常,我想打印它然后继续踢掉RunC。

var result = Try {
    new RunA()
    new RunB()
    new RunC()
}   catch { 
    case e: Throwable => e.printStackTrace()
    false
 }

除了将它们全部单独包裹在Try / Catch中之外,我确信有更好的方法可以做到这一点,这就是为什么我希望有人可以帮助解决这个问题。

我查看了“忽略”异常,但似乎完全忽略了我想要至少记录的异常。

谢谢!

3 个答案:

答案 0 :(得分:2)

首先,不要将try { ... } catch { ... }scala.util.Try{ ... }混合起来。

你可以

import scala.util._
val runA = Try{ new RunA }
val runB = Try{ new RunB }
val runC = Try{ new RunC }

然后按照您认为合适的方式处理异常。例如,如果要打印并继续,可以在那里处理try语句:

def getOrPrint[A](f: => A): Option[A] = Try{ f } match {
  case Success(x) => Some(x)
  case Failure(e) => e.printStackTrace; None
}

getOrPrint{ new RunA }
...

答案 1 :(得分:2)

使用scalaz可以有更优雅的方式来处理这类事情(例如,在这里阅读一篇文章以获得灵感:http://johnkurkowski.com/posts/accumulating-multiple-failures-in-a-ValidationNEL/),但只使用“Scalaz”,您可以执行以下操作:

import scala.reflect.ClassTag
import scala.util.{Try, Success, Failure}

def tryAndLog[T: ClassTag] = Try {
    implicitly[ClassTag[T]].runtimeClass.newInstance.asInstanceOf[T] // new instance
} match {
    case Success(_) => true
    case Failure(ex) => ex.printStackTrace ; false
}    

def tryRunAll = {
    val A = tryAndLog[RunA]
    val B = tryAndLog[RunB]
    val C = tryAndLog[RunC]
    A && B && C  // returns true if all invocations succeeded, false otherwise
}

答案 2 :(得分:1)

您正在将scala.util.Try与try {} catch {}混合使用,这些是不同的概念。尝试将函数包装到Success(结果)或Failure(错误)类中,try-catch就像Java try-catch。我建议你这样的事情:

  class RunA
  class RunB
  class RunC
  class Result(a: RunA, b: RunB, c: RunC)

  implicit class LogFailure[T](t: Try[T]) {
    def logFailure: Try[T] = t match {
      case scala.util.Failure(err) => err.printStackTrace(); t
      case _ => t
    }
  }

  val tryA= Try(new RunA())
  val tryB= Try(new RunB())
  val tryC = Try(new RunC())

  val result: Try[Result] = for {
    a <- tryA.logFailure
    b <- tryB.logFailure
    c <- tryC.logFailure
  } yield {
    // do smth with a, b, c
    new Result(a, b, c)
  }

如果A,B,C成功,您将获得成功(结果),如果其中一个失败,您将在第一个异常时获得失败,但是所有这些都将被记录(打印堆栈跟踪)