我正在关注这个题为:The case against checked exceptions的SO讨论,但是我无法关注应该使用RuntimeException的地方以及它与普通Exceptions及其子类的不同之处。谷歌搜索给了我一个复杂的答案,也就是说,它应该用于处理编程逻辑错误,并且应该在没有正常情况发生时抛出,例如在switch-case结构的默认块中。
请在这里详细解释一下RuntimeException。感谢。
答案 0 :(得分:18)
我无法完全遵循 应该使用RuntimeException
这可能是因为你正在查看一个论证,即人们对这一点的看法不一致。
和 它与正常情况有何不同 例外及其子类。
非常简单:Exception
的所有子类(RuntimeException
及其子类除外)都已检查,即编译器将拒绝您捕获的代码unelss或在方法签名。但是,RuntimeException
的子类未选中。
谷歌搜索给了我一个复杂的答案, 也就是说,它应该被用来处理 编程逻辑错误和 没有Exception时应该抛出 通常应该发生,例如在 switch-case的默认块 构造
这是传统的智慧,它表示对于程序可以有效处理的所有内容,您应该使用已检查的异常,因为编译器将强制您处理它们。相反,程序通常不能有效地处理程序员错误,因此不必检查它们。这就是Java Standard API使用RuntimeException
的方式。
您链接的讨论是由某些人(包括我)认为检查过的异常导致错误代码而不应该被使用的观点引发的。由于您无法在编译器中禁用异常检查,因此执行此操作的唯一方法是仅使用 RuntimeException
及其子类。
IMO支持这种观点的一个观察是,“仅针对程序员错误使用未经检查的异常”的传统观点实际上主要是向后推理的合理化:没有代码安全性原因,编译器不应强迫您处理程序员错误。但是,像NullPointerException
和ArrayIndexOutOfBoundsException
之类的东西几乎可以在任何地方出现,如果检查过,那么没人会想用Java编程。因此,语言设计者必须为这些做出一个例外,并使它们不受限制。为了解释这一点,他们提出了“未经检查的例程是针对程序员错误”的故事。
答案 1 :(得分:16)
来自 Effective Java 2nd Edition的引文,第58项:对可恢复条件使用已检查的异常和编程错误的运行时异常
Java编程语言提供三种throwable:已检查的异常,运行时异常和错误。程序员之间存在一些混淆,即何时适合使用各种throwable。虽然决策并不总是很明确,但有一些通用规则可以提供强有力的指导。
决定是否使用已检查例外或未经检查的例外的基本规则是:
- 使用已检查的例外情况,可以合理地预期来电者可以恢复。通过抛出已检查的异常,可以强制调用者在
catch
子句中处理异常或向外传播它。因此,声明抛出方法的每个已检查异常都是API用户的一个强有力的指示,即关联条件是调用该方法的可能结果。- 使用运行时异常来指示编程错误。绝大多数运行时异常都表示 precondition违规。违反前提条件的原因只是客户的API未能遵守API规范指定的合同。
以下是一个例子:
FileNotFoundException
是一个经过检查的例外。null
字符串作为文件名,那么应该抛出NullPointerException
(或者可能是IllegalArgumentException
- 另一个有争议的争论。 API的客户端应该提供有效的字符串值; null
不是。就API而言,这是一个程序员错误,很容易被预防。这两个例外都是运行时异常。第59项:避免不必要地使用已检查的例外还提供了其他指导:
经过检查的异常是Java编程语言的一个很棒的特性。与返回代码不同,他们强制程序员处理异常情况,大大提高可靠性。也就是说,过度使用已检查的异常可能会使API的使用变得不那么令人愉快。如果方法抛出一个或多个已检查的异常,则调用该方法的代码必须处理一个或多个
catch
块中的异常,或者必须声明它throws
异常并让它们向外传播。无论哪种方式,它给程序员带来了重大的负担。如果出现以下情况,那么负担是合理的:
- 通过正确使用API 和
无法阻止异常情况- 使用API的程序员在遇到异常时可以采取一些有用的操作。
除非这两个条件都成立,否则未经检查的异常更合适。
所以这里是 Effective Java 2nd Edition 推荐的简短摘要:
未经检查的异常定义为RuntimeException
及其子类,Error
及其子类。它们不必在方法的throws
子句中声明。