捕获 Exception 对象是否安全

2024-04-20

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

    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 中,我只会捕获将字符串解析为日期的异常,而不会捕获其余的异常,因为它们可能是致命的。我的理解是,抓住Exception意味着捕获任何非致命/非严重异常。因为它不是同一个捕获Throwable它是安全的——但真的是这样吗?使用此方法的基本原理是,未知的异常可能会从堆栈深处抛出,如果它们不是致命的,为什么不捕获所有异常。这一直是 Java 中的一个问题,在 Java 中,很容易从直接调用中找到可能的异常,但不能从更深层次的调用中找到可能的异常。这是 Scala 解决方案的基本意思是“捕获所有可恢复的异常”吗?

我的问题是;上面的代码被认为是良好的 Scala 风格,它是否“安全”,意味着比仅捕获字符串到 Date 转换异常更好。


解决问题的风格方面,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
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

捕获 Exception 对象是否安全 的相关文章

随机推荐

  • 闭包可能比当前函数的寿命更长

    我刚刚开始学习 Rust 为此 我正在用 Rust 重写我的 C 项目 但最大的问题是闭包的生命周期等 我创建了一个绝对最小的问题场景及以下 use std sync Arc use std cell RefCell Cell struct
  • 计算 3D 中两点之间的距离

    我的任务是创建主类 在其中将任意点的值初始化为 0 0 0 并且能够单独访问和改变所有三个值 x y z 为此 我使用了 getter 和 setter 我的下一个任务是在我的主类中创建一个方法 我将其称为 distanceTo 来计算两点
  • (更改)Angular2 中的事件钩子

    我知道 改变 event Binding在 angular2 中 但我很惊讶为什么我的代码没有按预期工作 我的代码在这里 http plnkr co edit 9pSWSeqBc5oaSAtsfwNY p preview http plnk
  • 为什么 Bootstrap 3 Collapse 与双击时的复选框状态不同步?

    根据这个问题 当复选框被选中时 Twitter Bootstrap 3 崩溃 https stackoverflow com questions 22480524 twitter bootstrap 3 collapse when chec
  • $scope.$on 在角度服务中的 $rootScope.$broadcast 之后不触发

    这可能是重复的问题 但我找到的解决此问题的方法在我的情况下不起作用 这就是我发布该问题的原因 我已经关注了service appRoot service MyService function rootScope var Messenger
  • Win32 API C++ 菜单栏

    我正在尝试学习一些基本的 win32 api 我看到将项目添加到菜单栏教程中提到使用类似以下内容 hMenubar CreateMenu hMenu CreateMenu AppendMenuW hMenu MF STRING IDM FI
  • Vaadin 更改默认会话过期通知?

    瓦丁7 6 2 如何更改默认的会话过期通知 消息和通知类型 要更改会话过期消息 您需要创建自己的SystemMessagesProvider 您在其中定义它 例如 在 Servlet 部署中 您可以执行以下操作 WebServlet url
  • Hibernate 3.6:SQL 方言中的 registerFunction 不起作用

    我放弃并询问社区 在我的项目中 我使用 Hibernate 3 6 4 Final 和自定义 sql 方言 public class ServiceAppMySQL5InnoDBDialect extends MySQL5InnoDBDia
  • Bash 脚本使用 FreeTDS 建立连接、交互、不退出(只是挂起)

    我在脚本中使用 FreeTDS 将记录插入 MSSQL 数据库 这USEandINSERT命令有效 但是exit命令没有 它挂起 我尝试过重定向stdoutbutcat抱怨 我想我会用Expect http www nist gov mel
  • 未能向 master 发送加入请求

    我使用的是elasticsearch版本1 3 0 重启数据节点后 无法检测到主节点 我收到错误failed to send join request to master 在错误日志中 app101 dGRBqTFTQfae76IFCjsM
  • strtolower() 用于 unicode/多字节字符串

    我的页面中有一些非英语 外语文本 但是当我尝试将其变为小写时 它的字符会转换为包含问号的黑色菱形 a echo b strtolower a returns 我已在元标记中设置了字符集 但这并没有解决问题 我该怎么做才能将字符串转换为小写而
  • vim 中项目列表的智能硬包装

    我喜欢 vim 而且我真的很喜欢在写文字时将它们硬包装起来 Tim Pope 的 markdown 插件很棒 并且构建得当我尝试硬包装项目列表时它可以正确完成工作 好吧 这就是我所说的正确完成工作的意思 here I write a lon
  • iPhone 就像在 Silverlight ListBox 上滚动一样

    我需要一个具有类似 iPhone 功能的 Silverlight 列表框 也就是动画滚动 点击拖动滚动 在鼠标释放事件之后 滚动将根据拖动的 速度 继续进行一段时间 我搜索过 没有找到提供此功能的控件供应商 那么问题是我应该如何构建它 我需
  • 如何使用 rvest R 从谷歌新闻中获取头条新闻?

    我想使用 R 中的 rvest 从谷歌新闻中获取头条新闻 到目前为止我已经做到了这一点 library rvest url read html https www google com search hl en tbm nws authus
  • 根据其他字段 javax.validation 的条件进行选项的字段验证

    如果存在另一个字段 我需要执行字段验证 它可以是值之一 import javax validation class Person NotBlank private String name private Long groupId Valid
  • Windows 在 PATH 中搜索可执行文件的相对顺序是什么?

    如果我有a com a cmd a bat and a exe我的文件中的 PATH 如果我只调用该命令 Windows 会选择哪一个a 这是微软官方指定的吗 我只是想包裹我的gvim exe可执行文件 n 但是我的gvim bat似乎既不
  • Elasticsearch 过滤器/计算嵌套字段

    我有带有嵌套字段的文档 如下所示 results id 1234 name asdf id 5678 name jkl ip 1 2 3 4 嵌套字段的映射如下所示 results type nested properties id typ
  • PDO 最后插入 ID 总是正确的吗?

    我有以下代码 我想问的是这个 想象一下 当两个人同时加载页面时 是否存在其他人的查询在检索到最后一个 ID 之前插入 从而混淆 ID 的危险 不 这种情况是不可能的 方法 db gt lastInsertId 返回此数据库连接的最后插入的
  • 将一个 XML 包含在另一个 XML 中并使用 python 解析它

    我想将一个 XML 文件包含在另一个 XML 文件中并用 python 解析它 我正在尝试通过 Xinclude 来实现它 有一个 file1 xml 看起来像
  • 捕获 Exception 对象是否安全

    我使用依赖于异常的 Java 库 简化代码如下 try val eventTime eventTimeString as Date catch case e Exception gt logger error s Can t parse e