代码之家  ›  专栏  ›  技术社区  ›  Rorick

在外部API中使用选中的异常是个好主意吗?

  •  3
  • Rorick  · 技术社区  · 14 年前

    在API中看到检查过的预期并不罕见,其中一个最著名的例子是 IOException 在里面 Closeable.close() . 经常处理这个例外情况真的让我很恼火。更令人恼火的例子是我们的一个项目。它由几个组件组成,每个组件声明特定的检查异常。问题(在我看来)是,在设计时,还不清楚某些例外会是什么。例如,组件 Configurator 宣布 ConfiguratorExeption . 当我问为什么不使用未检查的异常时,我被告知我们希望我们的应用程序是健壮的,而不是在运行时爆炸。但这是一个薄弱的论点,因为:

    1. 大多数例外情况都会使应用程序无法使用。是的,它不会爆炸,但它不能用消息来解释淹没日志。
    2. 这些例外并不具体,实际上意味着“发生了一些不好的事情”。客户机应该如何恢复?
    3. 事实上,所有恢复都是从日志异常中进行的,然后将其吞没。这是大范围的 try-catch 语句。

    我认为,这是一个反复出现的模式。但是仍然被检查的异常在API中被广泛使用。为什么会这样?是否有某些类型的API更适合检查异常?

    5 回复  |  直到 14 年前
        1
  •  2
  •   Jose Diaz    14 年前

    有很多 controversy 围绕这个问题。

    看看这篇关于那个主题的经典文章 http://www.mindview.net/Etc/Discussions/CheckedExceptions

    我个人倾向于使用 Runtime 异常本身,并且已经开始考虑在您的API中使用选中的异常是一个坏主意。

    事实上,一些非常流行的Java API已经开始做同样的事情,例如, 冬眠 已从版本3中删除对运行时检查异常的使用, 春天 框架还支持使用运行时而不是检查异常。

        2
  •  2
  •   Thorbjørn Ravn Andersen    14 年前

    大型库的一个问题是,它们没有记录所有可能抛出的异常,因此,如果一个未记录的runtimeexception恰好是从您不“拥有”的深层代码中抛出的,那么您的代码可能随时会爆炸。

    通过显式地声明所有这些,至少使用所述库的开发人员有编译器帮助正确地处理它们。

    没有什么比早上3点做法医分析更能发现某些情况引发了这样一个未声明的异常。

        3
  •  2
  •   user177800    14 年前

    检查异常只应针对 1) 例外 它们是成功法则的一个例外,最差的例外抛出是防御编码的可怕习惯。 2) 可诉的 由客户 . 如果发生API客户端不可能以任何方式影响的事情,则将其设为RuntimeException。

        4
  •  1
  •   Neil Coffey    14 年前

    对这件事有不同的看法,但我倾向于以下观点:

    • 已检查异常 表示一个事件,在某些可预测的、特殊的情况下,人们可以合理地预期它会发生,这些情况仍然“在程序/典型调用程序的正常操作条件下”,并且通常可以在调用堆栈上不太远的位置处理;
    • 未选中的异常 表示在程序的正常运行环境中,我们“不会真正期望发生”的情况,可以在调用堆栈的较高位置处理(或者在应用程序较简单的情况下,确实可能导致我们关闭应用程序);
    • 错误 表示一个条件,如果发生这种情况,我们通常希望导致我们关闭应用程序。

    例如,它完全在一个典型环境的领域内,在一些异常但相当可预测的条件下,关闭一个文件可能会导致I/O错误(当磁盘满时,在关闭时将缓冲区刷新到一个文件)。因此,让Closable抛出选中的IOException的决定可能是合理的。

    另一方面,在标准Java API中有一些示例,其中的决策是不可防御的。我要说的是,当涉及到检查的异常时,XML API通常过于繁琐(为什么找不到一个您真正希望在典型应用程序中发生并处理的XML解析器…?)和反射API一样(通常您真的希望找到类定义,并且无论它们是否是…,都无法继续进行)。但许多决定都是有争议的。

    一般来说,我同意“配置异常”类型的异常应该取消选中。

    记住,如果您正在调用一个方法,该方法声明了一个选中的异常,但您“真的不希望它被抛出,而且如果它被抛出,真的不知道该怎么做”,那么您可以通过编程方式“耸耸肩”并将其重新强制转换为runtimeexception或error…

        5
  •  0
  •   CurtainDog    14 年前

    实际上,你可以使用 Exception tunneling 这样,一般的异常(如configuratorException)就可以提供关于发生错误的更多细节(如fileNotFound)。

    不过,总的来说,我会谨慎对待,因为这可能是 leaky abstraction (任何人都不应该关心配置程序是否试图通过网络或其他方式从文件系统、数据库中提取数据)

    如果您使用的是选中的异常,那么至少您将 知道 哪里和为什么你的抽象是泄漏的。嗯,这是件好事。