在外部API中使用已检查的异常是一个好主意吗?

时间:2010-07-28 20:39:00

标签: java exception-handling

在API中查看已检查的预测并不罕见,其中一个最着名的示例是Closeable.close()中的IOException。经常处理这个异常真让我烦恼。更令人讨厌的例子是我们的一个项目。它由几个组件组成,每个组件声明特定的已检查异常。问题(在我看来)是在设计时,并不确切知道某些例外是什么。因此,例如,组件Configurator声明为ConfiguratorExeption。当我问为什么不使用未经检查的异常时,我被告知我们希望我们的应用程序是健壮的,而不是在运行时。但它因为:

而成为一个弱论点
  1. 大多数这些例外都会使应用无法使用。是的,它不会爆炸,但它无法通过消息使洪水记录任何事情。
  2. 这些例外并不具体,实际上意味着'发生了一些不好的事'。客户应该如何恢复?
  3. 事实上,所有恢复都包括记录异常,然后吞下它。这是在大try-catch语句中执行的。
  4. 我认为,这是一种反复出现的模式。但仍然检查过的异常在API中被广泛使用。这是什么原因?是否有某些类型的API更适合检查异常?

5 个答案:

答案 0 :(得分:2)

只有在 1) 例外 的事情中才会抛出已检查的例外情况它们是成功规则的例外,大多数可怜的异常抛出都是可怕的客户的防御性编码和 2) 可操作 的习惯。如果发生某些事情,API的客户端不可能以任何方式影响它,使其成为RuntimeException。

答案 1 :(得分:2)

围绕这个问题已经有很多controversy

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

我个人倾向于支持自己使用Runtime例外,并开始考虑在您的API中使用已检查的例外是一个坏主意。

事实上,一些非常流行的Java API已经开始做同样的事情了,例如, Hibernate 从版本3中删除了对运行时的已检查异常的使用, Spring 框架也支持在已检查的异常中使用Runtime。

答案 2 :(得分:2)

大型库的一个问题是它们没有记录可能抛出的所有异常,所以如果一个未记录的RuntimeException恰好是从你没有“拥有”的深层代码中抛出的话,你的代码可能会随时轰炸”

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

没有什么比在早上3点进行法医分析更能发现某些情况引发了这种未申报的例外情况。

答案 3 :(得分:1)

对此事有不同的看法,但我倾向于按如下方式查看:

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

例如,它完全属于典型环境的范围,在某些特殊情况下 - 但是相当可预测 - 条件下,关闭文件可能会导致I / O错误(在磁盘关闭时将缓冲区刷新到文件已满)。因此,让Closable抛出一个经过检查的IOException的决定可能是合理的。

另一方面,标准Java API中有一些例子,其决策不太可靠。我会说,在检查异常时,XML API通常过于繁琐(为什么找不到你真正希望在典型应用程序中发生和处理的XML解析器......?),反思API也是如此(你通常真的希望找到类定义,不管它们不是......都不能发挥作用。但许多决定都是有争议的。

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

请记住,如果你正在调用一个方法来声明一个已检查的异常,但你“真的不希望它被抛出,并且真的不知道如果它被抛出该怎么办”,那么你可以通过编程方式“耸耸肩“并将其重新投射到RuntimeException或Error ...

答案 4 :(得分:0)

事实上,您可以使用Exception tunneling,以便通用异常(例如您的ConfiguratorException)可以提供有关错误的更多详细信息(例如FileNotFound)。

一般情况下,我会对此提出警告,因为这可能是leaky abstraction(没有人应该关心你的配置器是否试图从文件系统,数据库,网络或其他任何方面提取数据)

如果您使用的是检查异常,那么至少您知道您的抽象漏洞的位置和原因。恕我直言,这是一件好事。