Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
有效的 Java 编程语言代码必须遵守 the Catch or Specify Requirement (捕获或指定要求) (译注:后文统一不翻译)。这意味着可能抛出某些异常的代码必须包含以下任一项:
不符合 the Catch or Specify Requirement 的代码将无法编译。
并非所有异常都受 the Catch or Specify Requirement 的约束。为了理解原因,我们需要了解三个基本类别的异常,其中只有一个受要求限制。
第一种异常是 checked exception (检查型异常)。这些是编写良好的应用程序应该预期和恢复的特殊状态。例如,假设应用程序提示用户输入文件名,然后通过将名称传递给 java.io.FileReader
的构造函数来打开该文件。通常,用户提供存在的,可读的文件的名称,因此 FileReader
对象的构造成功,并且应用程序的执行正常进行。但有时用户提供不存在的文件的名称,构造函数抛出 java.io.FileNotFoundException
。一个编写良好的程序将捕获此异常并通知用户该错误,可能会提示输入正确的文件名。
检查型异常受限于 the Catch or Specify Requirement。除 Error
,RuntimeException
及它们的子类指示的异常外,所有异常都是检查型异常。
第二种异常是 error (错误)。这些是应用程序外部的特殊状态,应用程序通常无法预测或恢复。例如,假设应用程序成功打开文件以进行输入,但由于硬件或系统故障而无法读取文件。不成功的读取将抛出 java.io.IOError
。应用程序可能会选择捕获此异常,以便通知用户该问题 但是程序打印堆栈跟踪并退出也可能有意义。
错误 不受限于 the Catch or Specify Requirement. 错误是 Error
及其子类指示的异常。
第三种异常是 runtime exception (运行时异常)。这些是应用程序内部的特殊情况,应用程序通常无法预测或恢复。这些通常表示编程错误,例如逻辑错误或 API 的不当使用。例如,考虑前面描述的将文件名传递给 FileReader
的构造函数的应用程序。如果逻辑错误导致 null
传递给构造函数,则构造函数将抛出 NullPointerException
。应用程序可以捕获此异常,但消除导致异常发生的错误可能更有意义。
运行时异常 不受限于 the Catch or Specify Requirement。运行时异常是 RuntimeException
及其子类指示的异常。
错误和运行时异常统称为 unchecked exceptions (非检查型异常)。
一些程序员认为 the Catch or Specify Requirement 是异常机制中的一个严重缺陷,并通过使用非检查型异常代替检查型异常来绕过它。一般情况下,不建议这样做。Unchecked Exceptions The Controversy 部分讨论何时适合使用非检查型异常。