【问题标题】:Please explain RuntimeException in Java and where it should be used请解释 Java 中的 RuntimeException 以及应该在哪里使用它
【发布时间】:2011-04-02 05:18:54
【问题描述】:

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

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

【问题讨论】:

    标签: java exception runtimeexception


    【解决方案1】:

    我无法准确追踪到哪里 应该使用 RuntimeException

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

    和 它与正常有什么不同 异常及其子类。

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

    谷歌搜索给了我一个复杂的答案, 也就是应该用来处理 与编程逻辑错误和 没有异常时应该抛出 通常应该发生,例如在 switch-case 的默认块 构造。

    这是传统观点,即对于程序可以有效处理的所有内容,您应该使用检查异常,因为编译器会强制您处理它们。相反,程序通常不能有效地处理程序员错误,因此不必检查它们。这就是 Java 标准 API 使用 RuntimeException 的方式。

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

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

    【讨论】:

    • 很好的答案,但它可能应该阅读“所有异常子类 - 除了 RuntimeException - 都已检查”,因为 RuntimeException 是 Exception 的子类。
    • 所以,如果我从一个方法(比如method1)抛出一个RuntimeException,我可以在调用这个method1的方法中忽略它吗?因为,在异常的情况下,method1 需要在 try-catch 短语中,或者调用它的方法本身应该抛出异常。
    • @emory:对,我会澄清一下,@euphoria83:完全正确。
    【解决方案2】:

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

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

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

    • 对调用者可以合理预期恢复的情况使用检查异常。通过抛出已检查的异常,您可以强制调用者在 catch 子句中处理异常或将其向外传播。因此,声明方法抛出的每个已检查异常都向 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 子句中声明。

    参考文献

    相关问题

    【讨论】:

    • +1 "使用运行时异常来指示编程错误。"可能是最有用的建议。
    猜你喜欢
    • 1970-01-01
    • 2017-07-10
    • 1970-01-01
    • 1970-01-01
    • 2012-03-26
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    相关资源
    最近更新 更多