有效的Java编程语言代码必须遵守捕获(Catch指定要求(Specify Requirement。这意味着可能抛出某些异常的代码必须由以下任意一个括起来:

  • 一个是捕获异常的try语句。try必须为异常提供了一个处理程序,如在 捕获和处理异常
  • 一个指定可以抛出异常的方法。方法必须提供列出异常的throws子句,如 指定方法抛出的异常中所述。

无法满足“捕获”或“指定要求”的代码将无法编译。
并非所有异常都必须符合“捕获”或“指定要求”。要理解原因,我们需要查看三种基本的异常类别,其中只有一种受要求约束。

三种异常

第一种异常是检查异常(checked exception。这些是编写良好的应用程序应该预期,并从中恢复的异常条件。例如,假设应用程序提示用户输入文件名,然后通过将名称传递给的构造器java.io.FileReader来打开文件。通常,用户提供现有的可读文件的名称,因此,FileReader对象构造成功,并且应用程序的执行正常进行。但是有时用户会提供一个不存在的文件名,而构造函数抛出java.io.FileNotFoundException。编写良好的程序将捕获此异常并通知用户错误,可能提示输入正确的文件名。
检查异常 “捕获”或“指定要求”的约束(**subject**。所有异常都是检查异常,除了由ErrorRuntimeException和它们的子类表示的那些。
第二种异常是错误(error。这些是应用程序外部的特殊条件,应用程序通常无法预期或从中恢复。例如,假设应用程序成功打开了文件以供输入,但是由于硬件或系统故障而无法读取该文件。不成功的读取将抛出java.io.IOError。应用程序可能选择捕获此异常,以便将问题通知用户-但对于程序来说,打印堆栈跟踪并退出也可能是有意义的。
错误不受 “捕获”或“指定要求”的约束。错误是由Error及其子类指示的那些异常。
第三种异常是运行时异常(runtime exception。这些是应用程序内部的特殊条件,应用程序通常无法预期或从中恢复。这些通常表示编程错误,例如逻辑错误或API使用不当。例如,考虑先前描述的应用程序,该应用程序将文件名传递给的构造函数FileReader。如果逻辑错误导致将一个 null传递给构造函数,则构造函数将抛出 NullPointerException。应用程序可以捕获此异常,但是消除导致异常发生的错误可能更有意义。
运行时异常不受 “捕获”或“指定要求”的约束。运行时异常是由RuntimeException及其子类指示的异常。
错误和运行时异常统称为未检查异常(**unchecked exceptions**

绕过捕获或指定

一些程序员认为“捕获”或“指定要求”是异常机制中的严重缺陷,并通过使用未检查异常代替检查异常来绕过它。通常,不建议这样做。未检查异常—争议部分讨论何时使用未检查异常是适当的。