我正在使用一些客户端库,并使用scala.util.control.Exception.ignoring
ignoring(classOf[ReallyNotThatExceptionalException]) {
stuff()
}
现在该库已更改为将所有exceptionn包装在另一个异常类中,这迫使我将代码更改为:
try { stuff() }
catch {
case e:WrapperException if e.getCause != null && e.getCause.isInstanceOf[ReallyNotThatExceptionalException] => { }
}
因此,我正在寻找一种更易读的方式来表达"捕捉由"引起的异常。
答案 0 :(得分:13)
0 __的回答很好,但如果你没有被迫为每个潜在的异常写一个特定的对象(CausedByFoo
)会更好。
碰巧的是,没有太多要改变以使用通用的CausedBy
辅助对象:
class Foo(message: String) extends Exception(message)
class Bar(cause: Throwable) extends Exception(cause)
object CausedBy {
def unapply(e: Throwable): Option[Throwable] = Option(e.getCause)
}
def test(block: => Unit): String =
try {
block
"ok"
} catch {
case CausedBy(ex: Foo) => "not ok: " + ex.getMessage
}
test(println("hello"))
test(println("hello".toInt)) // uncaught exception
test(throw new Bar(new Foo("Ooops, foo error!"))) // caught
很明显,您可以将CausedBy
用于任何例外情况(例如,通过执行case CausedBy(ex: Baz)
。
你甚至可以嵌套它来处理由异常引起的异常引起的异常(做case CausedBy(CausedBy(ex: Foo))
答案 1 :(得分:4)
catch
块可以处理任何常规模式匹配,所以
class Foo extends Exception
class Bar(cause: Exception) extends Exception(cause)
object CausedByFoo {
def unapply(e: Exception): Boolean = e.getCause match {
case _: Foo => true
case _ => false
}
}
def test(block: => Unit): String =
try {
block
"ok"
} catch {
case CausedByFoo() => "not ok"
}
test(println("hello"))
test(println("hello".toInt)) // uncaught exception
test(throw new Bar(new Foo)) // caught
答案 2 :(得分:0)
我调整了Régis的答案,以允许同时匹配外部和内部异常类型。
trait CausedBy[T <: Throwable] {
def unapply(e: T): Option[Throwable] = Option(e.getCause)
}
object IOExceptionCausedBy extends CausedBy[IOException]
然后您可以像这样进行匹配:
try {
// do some DB thing
} catch {
case IOExceptionCausedBy(exception: PSQLException) =>
// handle PSQL exception
}