10

我在 SO 上关注这个精彩的讨论,标题为:针对已检查异常的案例,但我无法了解应该在哪里使用 RuntimeException 以及它与普通异常及其子类有何不同。Googling 给了我一个复杂的答案,就是它应该用来处理编程逻辑错误,应该在正常情况下不应该发生异常的时候抛出,比如在 switch-case 构造的默认块中。

您能否在此处更详细地解释 RuntimeException。谢谢。

4

2 回答 2

22

我不知道应该在哪里使用 RuntimeException

这可能是因为您正在查看一个论点,即人们在这一点上存在分歧。

以及它与普通异常及其子类有何不同。

非常简单:检查Exception所有子类(除了RuntimeException及其子类),即编译器将拒绝您捕获或在方法签名中声明它们的代码。但是, 的子类是uncheckedRuntimeException

Googling 给了我一个复杂的答案,就是应该用它来处理编程逻辑错误,应该在正常不应该发生异常的时候抛出,比如在 switch-case 构造的默认块中。

这是传统观念,它说对于程序可以有效处理的所有事情,您都应该使用检查异常,因为编译器会强迫您处理它们。相反,程序通常不能有效地处理程序员错误,因此不必检查它们。这就是 Java 标准 API 使用RuntimeException.

您链接到的讨论是由一些人(包括我)的观点引发的,他们认为检查的异常会导致错误的代码,因此不应使用。由于您无法在编译器中禁用异常检查,因此唯一的方法是 RuntimeException使用及其子类。

IMO 支持这一观点的一个观察结果是,“仅对程序员错误使用未经检查的异常”的传统智慧实际上主要是向后推理的合理化:编译器不应该强迫您与程序员打交道没有代码安全理由错误。NullPointerException然而,类似的东西ArrayIndexOutOfBoundsException几乎可以在任何地方出现,如果这些被选中,没有人会想用 Java 编程。因此,语言设计者不得不为它们做一个,呵呵,例外,并让它们不受检查。为了解释这一点,他们提出了“未经检查的异常是针对程序员错误”的故事。

于 2010-08-22T08:20:51.930 回答
18

引自Effective Java 2nd Edition,第 58 条:对可恢复条件使用检查异常和对编程错误使用运行时异常

Java 编程语言提供了三种 throwable:检查异常运行时异常错误。程序员对于何时适合使用每种 throwable 存在一些混淆。虽然决定并不总是明确的,但有一些一般规则可以提供强有力的指导。

决定是使用已检查异常还是未检查异常的基本规则是:

  • 对于可以合理预期调用者从中恢复的条件,请使用已检查异常。通过抛出已检查异常,您可以强制调用者在catch子句中处理异常或将其向外传播。因此,声明方法抛出的每个已检查异常都向 API 用户有力地表明相关条件是调用该方法的可能结果。
  • 使用运行时异常来指示编程错误。绝大多数运行时异常表明违反了先决条件。前提条件违反只是API的客户端未能遵守 API 规范指定的合同。

这是一个例子:

  • 尝试读取任意名称的文件时,该文件可能不存在。当文件不存在时(例如,它之前可能存在但后来被意外删除),这并不是严格意义上的编程错误。客户可能希望从中恢复。因此,FileNotFoundException是一个检查异常。
  • 如果你给出一个null字符串作为文件名,那么NullPointerException(或者可能是IllegalArgumentException另一个有争议的辩论)应该被抛出。API 的客户端应该提供一个有效的字符串值;null不是。就 API 而言,这是一个很容易预防的程序员错误。这两个异常都是运行时异常。

第 59 条:避免不必要地使用受检异常也提供了额外的指导:

检查异常是 Java 编程语言的一个很棒的特性。与返回码不同,它们迫使程序员处理异常情况,大大提高了可靠性。也就是说,过度使用检查异常会使 API 的使用变得不那么愉快。如果一个方法抛出一个或多个已检查异常,则调用该方法的代码必须在一个或多个catch块中处理异常,或者必须将其声明throws为异常并让它们向外传播。无论哪种方式,它都给程序员带来了不小的负担。

在以下情况下,负担是合理的:

  • 不能通过正确使用 API 来防止异常情况,并且
  • 一旦遇到异常,使用 API 的程序员可以采取一些有用的措施。

除非这两个条件都成立,否则未经检查的异常更合适。

下面是Effective Java 2nd Edition推荐的简短摘要:

  • 由于 API 用户错误而发生的可预防异常应取消选中
  • 不能合理处理的异常也应该取消选中
  • 否则,应检查异常。

也可以看看

  • 有效的 Java 第 2 版
    • 第 58 条:对可恢复条件使用检查异常,对编程错误使用运行时异常
    • 第 59 条:避免不必要地使用受检异常
    • 第 60 条:赞成使用标准例外
    • 第 61 条:抛出适合抽象的异常
    • 第 62 条:记录每个方法抛出的所有异常

技术定义

未经检查的异常被定义为RuntimeException及其子类Error及其子类。它们不必在方法的throws子句中声明。

参考

相关问题

于 2010-08-22T08:19:59.597 回答