在我当前的方法中,我试图进行一系列调用,如果其中任何一个失败,我希望能够继续运行其余部分(同时捕获抛出的异常)。我很难在Scala中搞清楚这一点。
所以在这个例子中,我想开始这些调用 - RunA,RunB和RunC但是如果RunB抛出异常,我想打印它然后继续踢掉RunC。
var result = Try {
new RunA()
new RunB()
new RunC()
} catch {
case e: Throwable => e.printStackTrace()
false
}
除了将它们全部单独包裹在Try / Catch中之外,我确信有更好的方法可以做到这一点,这就是为什么我希望有人可以帮助解决这个问题。
我查看了“忽略”异常,但似乎完全忽略了我想要至少记录的异常。
谢谢!
答案 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成功,您将获得成功(结果),如果其中一个失败,您将在第一个异常时获得失败,但是所有这些都将被记录(打印堆栈跟踪)