Java™ 教程(捕获或指定要求)

7次阅读

共计 1798 个字符,预计需要花费 5 分钟才能阅读完成。

捕获或指定要求
有效的 Java 编程语言代码必须遵守捕获或指定需求,这意味着可能抛出某些异常的代码必须包含以下任一项:

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

不符合捕获或指定要求的代码将无法编译。
并非所有异常都受捕获或指定要求的约束,为了理解原因,我们需要查看三个基本类别的异常,其中只有一个受要求限制。
三种异常
第一种异常是已检查的异常,这些都是编写良好的应用程序应该预料到并从中恢复的异常情况。例如,假设应用程序提示用户输入文件名,然后通过将名称传递给 java.io.FileReader 的构造函数来打开该文件,通常,用户提供现有可读文件的名称,因此 FileReader 构造对象成功,并且应用程序的执行正常进行。但有时用户提供不存在的文件的名称,构造函数抛出 java.io.FileNotFoundException,一个编写良好的程序将捕获此异常并通知用户该错误,可能提示更正的文件名。
已检查的异常情况受捕获或指定要求的约束,除 Error、RuntimeException 及其子类表示的异常外,所有异常都是经过检查的异常。
第二种异常是错误,这些是应用程序外部的异常情况,应用程序通常无法预测或恢复。例如,假设应用程序对于输入成功打开文件,但由于硬件或系统故障而无法读取文件,不成功的读取将抛出 java.io.IOError,应用程序可能会选择捕获此异常,以便通知用户该问题 — 但是程序打印堆栈跟踪并退出也可能有意义。
错误不受捕获或指定要求的约束,错误是 Error 及其子类表示的异常。
第三种异常是运行时异常,这些是应用程序内部的异常情况,应用程序通常无法预测或恢复,这些通常表示编程 bug,例如逻辑错误或 API 的不当使用。例如,考虑前面描述的应用程序将文件名传递给 FileReader 的构造函数,如果逻辑错误导致将 null 传递给构造函数,则构造函数将抛出 NullPointerException,应用程序可以捕获此异常,但消除导致异常发生的 bug 可能更有意义。
运行时异常不受捕获或指定要求的约束,运行时异常是 RuntimeException 及其子类表示的异常。
错误和运行时异常统称为未经检查的异常。
通过方法抛出指定异常
有时,代码可以捕获可能在其中发生的异常,但是,在其他情况下,最好让调用堆栈中进一步的方法处理异常。例如,如果你将 ListOfNumbers 类作为类包的一部分提供,则可能无法预测包的所有用户的需求,在这种情况下,最好不捕获异常并允许调用堆栈进一步的方法来处理它。
如果 writeList 方法没有捕获可能在其中发生的已检查异常,则 writeList 方法必须指定它可以抛出这些异常,让我们修改原始的 writeList 方法来指定它可以抛出而不是捕获它们的异常,这是不能编译的 writeList 方法的原始版本。
public void writeList() {
PrintWriter out = new PrintWriter(new FileWriter(“OutFile.txt”));
for (int i = 0; i < SIZE; i++) {
out.println(“Value at: ” + i + ” = ” + list.get(i));
}
out.close();
}
要指定 writeList 可以抛出两个异常,请将 throws 子句添加到 writeList 方法的方法声明中,throws 子句包含 throws 关键字,后跟逗号分隔的该方法抛出的所有异常列表,该子句在方法名称和参数列表之后以及定义方法范围的大括号之前,这是一个例子。
public void writeList() throws IOException, IndexOutOfBoundsException {
请记住,IndexOutOfBoundsException 是未经检查的异常,在 throws 子句中包含它不是强制性的,你可以仅写下面的内容。
public void writeList() throws IOException {
绕过捕获或指定
一些程序员认为捕获或指定要求是异常机制中的一个严重缺陷,并通过使用未经检查的异常代替已检查的异常来绕过它,通常,不建议这样做,未经检查的异常 — 争议部分讨论何时适合使用未经检查的异常。

上一篇:什么是异常?

正文完
 0