捕获Exception对象是否安全? [英] Is it safe to catch an Exception object

查看:95
本文介绍了捕获Exception对象是否安全?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用依赖异常的Java库。下面的简化代码:

I use a Java lib that relies on exceptions. Simplified code below:

    try {
      val eventTime = eventTimeString.as[Date]
    } catch {
      case e: Exception =>
        logger.error(s"Can't parse eventTime from $eventTimeString", e)
        // take action for the bad Date string.
    }

在Java中,我只能捕获将字符串解析为Date的异常,让其余的都保持原状,因为它们可能是致命的。在这里我的理解是,捕获 Exception 意味着捕获任何非致命/非严重的异常。由于它不是相同的捕获 Throwable ,所以很安全-但这真的吗?使用此方法的理由是,未知异常可能从更深的堆栈中抛出,如果它们不是致命的,为什么不捕获所有异常。这在Java中一直是一个问题,在Java中很容易从您进行的直接调用中找到可能的异常,而从更深层的调用中很难找到。

In Java I would catch only the exception from parsing a string into a Date, letting the rest go uncaught since they could be fatal. Here my understanding is that catching Exception means to catch ANY non-fatal/non-serious exceptions. Since it is not the same a catching Throwable it is safe—but is it truly? The rationale for using this is that unknown exceptions might be thrown from deeper in the stack and if they are not fatal, why not catch all of them. This has always been a problem in Java where it is easy to find possible exceptions from the direct call you are making but not from deeper. Is this the Scala solution that basically means, 'catch all recoverable exceptions"?

我的问题是;以上代码是否被认为是良好的Scala风格,是否安全?

My question is; is the above code considered good Scala style, is it "safe", meaning better than catching only the string to Date cast exception.

推荐答案

解决问题的样式方面,尝试,如@LuisMiguelMejiaSuarez所建议的那样,提供了更惯用的Scala样式,例如

Addressing the style aspect of the question, Try, as suggested by @LuisMiguelMejiaSuarez, provides a more idiomatic Scala style like so

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
}

从语法上看并没有太大区别,但是从概念上讲这是一个很大的转变,因为成功 Failure 表示常规的,而不是某些值特殊的控制结构成功的值类似于 7 的值,而尝试捕获更像是 while if-else 控制工具。

Syntactically it appears not much different, however conceptually it is quite a shift because Success and Failure represent regular values as opposed to some exceptional control-structure. Success is a value like 7 is value, whilst try-catch is more like while or if-else control facility.

包装任何可能引发 Try 的库调用(例如由Java库提供的),我们可以利用收益糖来像这样链接调用

Wrapping any library call that might throw in Try, provided by, say, Java libraries, we could make use of for-yield sugar to chain calls like so

for {
  a <- Try(foo)
  b <- Try(bar)
  c <- Try(qux)
} yield {
  // work with a, b and c
}

其中

def foo: Int = {
  throw new TimeoutException("foo")
  42
}

def bar: String = {
  throw new IllegalArgumentException("bar")
  "hello"
}

def qux: Boolean = {
  throw new NullPointerException("qux")
  true
}

我们可以按顺序阅读此链条,而不必中断我们的思想流程,并尝试了解某些​​例外情况控制结构适合该算法。

We can read this chain sequentially without having to interrupt our flow of thought and try to understand how some exceptional control structure fits into the algorithm.

关于问题的安全性,可以说,我们不应该捕获致命异常,例如 LinkageError ,实际上 Try 与以下例外不匹配

Regarding safety aspect of the question, arguably, we should not catch fatal exception such as LinkageError, and indeed Try does not match the following exceptions

VirtualMachineError
ThreadDeath
InterruptedException
LinkageError
ControlThrowable

constructed

object Try {
  def apply[T](r: => T): Try[T] =
    try Success(r) catch {
      case NonFatal(e) => Failure(e)
    }
}

其中 NonFatal

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
}

这篇关于捕获Exception对象是否安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆