我遇到了需要调用 foo
的情况方法,如果失败调用bar
方法,然后重新抛出原始异常(包装)。
我的问题是bar
方法也可能失败,其异常信息也很重要。
当我创建一个新的异常时,只有一个原因,而我有两个原因。我可以创建类似 class MyException(cause1, cause2) extends RuntimeException(cause1)
的东西但是cause2
将超出异常所具有的标准机制(堆栈跟踪等)。
有没有更好的方法来处理这种情况?
以下代码是一个简化的示例。
// I can't change this code
def foo:String = throw new FooException("foo method fails")
def bar:String = throw new BarException("bar method fails")
// my code
try {
foo
} catch {
case error1:FooException =>
try {
// if foo fails, I want to call bar
bar
throw new MyException("my exception", error1)
} catch {
case error2:BarException =>
// but bar could fail too
throw new MyException("my exception", ???)
// if my cause is error1, I lost error2 information (message and stack)
// if my cause is error2, I lost error1 information (message and stack)
}
}
提前谢谢您。
最佳答案
您可以将 MyException
throwable 与一个或两个“抑制”异常打包在一起。
val myEx = new MyException("my exception")
myEx.addSuppressed(error1)
myEx.addSuppressed(error2)
throw myEx
然后由捕获代码来解压它。
case err : MyException =>
val arr :Array[Throwable] = err.getSuppressed
// arr contains all the "suppressed" exceptions that were added,
// stack traces and all
不过,可以说最好是表达类型系统中错误的可能性,而不是将其留给(可能不存在的)捕获代码来执行正确的操作。
import util.Try
val res :Either[List[Throwable],String] =
Try(foo).fold(fErr =>
Try(bar).fold(bErr => Left(fErr::bErr::Nil), _ => Left(fErr::Nil))
, Right(_))
从那里您可以根据需要继续操作。
res match {
case Right(s) => println(s) //foo result string
case Left(lst) =>
println(lst.map(_.getMessage()).mkString(",")) //foo method fails,bar method fails
lst.foreach(_.printStackTrace()) //both stack traces
}
关于scala - 两个异常 "at the same time",处理这种情况的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52339385/