解决问题的风格方面,Try
正如 @LuisMiguelMejiaSuarez 所建议的,提供了更惯用的 Scala 风格,如下所示
Try(eventTimeString.as[Date]) match {
case Success(eventTimeDate) => // work with eventTimeDate
case Failure(e: IllegalArgumentException) => // work with e
case Failure(e: NullPointerException) => // work with e
...
case Failure(e) => // work with e
}
从语法上看,它看起来没有太大不同,但从概念上讲,这是一个很大的转变,因为Success
and Failure
代表常规values与一些特殊的情况相反控制结构. Success
是一个像这样的值7
是价值,同时try-catch
更像是while
or if-else
控制设施。
包装任何可能抛出的库调用Try
,由 Java 库提供,我们可以利用 for-yield 糖来像这样链接调用
for {
a <- Try(foo)
b <- Try(bar)
c <- Try(qux)
} yield {
// work with a, b and c
}
where
def foo: Int = {
throw new TimeoutException("foo")
42
}
def bar: String = {
throw new IllegalArgumentException("bar")
"hello"
}
def qux: Boolean = {
throw new NullPointerException("qux")
true
}
我们可以按顺序阅读这条链,而不必中断我们的思维流程,并尝试理解一些特殊的控制结构如何适应算法。
关于问题的安全方面,可以说,我们不应该捕获致命异常,例如LinkageError
,而且确实Try
不匹配以下异常
VirtualMachineError
ThreadDeath
InterruptedException
LinkageError
ControlThrowable
如图所示建 https://github.com/scala/scala/blob/a73bacc2499170688eda6e0b2a912be5524da737/src/library/scala/util/Try.scala#L211
object Try {
def apply[T](r: => T): Try[T] =
try Success(r) catch {
case NonFatal(e) => Failure(e)
}
}
where NonFatal https://github.com/scala/scala/blob/a73bacc2499170688eda6e0b2a912be5524da737/src/library/scala/util/control/NonFatal.scala#L35 is
object NonFatal {
def apply(t: Throwable): Boolean = t match {
case _: VirtualMachineError | _: ThreadDeath | _: InterruptedException | _: LinkageError | _: ControlThrowable => false
case _ => true
}
def unapply(t: Throwable): Option[Throwable] = if (apply(t)) Some(t) else None
}