199. Java 异常 - 异常处理 “秘籍”:try、catch、finally 如何协同?
在前面的部分中,我们已经讨论了如何构建 try、catch 和 finally 代码块。在这一节中,我们将把这些概念结合在一起,分析 writeList() 方法的完整实现,并探讨它在不同情况下的行为。
writeList() 方法的完整代码如下:
public void writeList() {
PrintWriter out = null;
try {
System.out.println("Entering try statement");
out = new PrintWriter(new FileWriter("OutFile.txt"));
for (int i = 0; i < SIZE; i++) {
out.println("Value at: " + i + " = " + list.get(i));
}
} catch (IndexOutOfBoundsException e) {
System.err.println("Caught IndexOutOfBoundsException: " + e.getMessage());
} catch (IOException e) {
System.err.println("Caught IOException: " + e.getMessage());
} finally {
if (out != null) {
System.out.println("Closing PrintWriter");
out.close();
} else {
System.out.println("PrintWriter not open");
}
}
}
关键点:
- 该方法首先创建一个
PrintWriter来写入文件。如果文件创建失败或尝试写入时发生错误,就会抛出IOException。 - 在
for循环中,如果访问list的某个索引超出范围,将会抛出IndexOutOfBoundsException。 - 不论是否发生异常,
finally块中的代码都会执行,确保PrintWriter被正确关闭,避免资源泄漏。
🚨 Scenario 1: An Exception Occurs (异常发生时)
错误发生的情况:
当创建 FileWriter 时,可能由于多种原因抛出 IOException。例如,如果程序无法创建或写入指定的文件,FileWriter 构造函数会抛出该异常。
当 FileWriter 抛出 IOException 时,Java 会立即停止执行 try 块中的后续代码,并开始查找合适的异常处理器。此时,异常会从方法调用栈的顶部向下传递,寻找适当的处理方法。
如何处理异常?
- 如果
IOException被抛出,Java 会依次检查writeList()方法中的catch块。首先检查IndexOutOfBoundsException,但它不匹配,所以接着检查IOException,这时找到匹配的异常处理器。 - 异常处理器执行后,程序会进入
finally块,不管是否抛出了异常,finally块的代码都会执行。 - 如果
FileWriter没有成功创建,那么out.close()语句不会执行,因为PrintWriter对象out没有被打开。
输出示例(发生 IOException 时):
Entering try statement
Caught IOException: OutFile.txt
PrintWriter not open
解释:
Entering try statement:表示程序进入了try块。Caught IOException: OutFile.txt:表示抛出了IOException,并显示了错误信息。PrintWriter not open:表示由于FileWriter创建失败,PrintWriter没有打开,因此没有关闭操作。
✅ Scenario 2: The try Block Exits Normally (正常退出 try 块)
正常执行的情况:
如果 try 块中的所有语句都执行成功且没有异常抛出,程序会正常退出 try 块,接着进入 finally 块。
正常执行流程:
try块中的代码执行完成,PrintWriter对象成功创建,并写入文件。- 执行到
finally块时,PrintWriter被关闭,确保资源得到释放。
输出示例(无异常时):
Entering try statement
Closing PrintWriter
解释:
Entering try statement:表示程序进入了try块并开始执行。Closing PrintWriter:表示PrintWriter被成功创建并关闭,资源得到了释放。
🔑 关键点总结:
- 异常发生时的处理流程:
- 当异常发生时,程序会立即跳转到对应的
catch块处理异常。 - 处理完异常后,无论是否发生异常,
finally块的代码都会执行,用于释放资源。
- 当异常发生时,程序会立即跳转到对应的
- 正常执行的处理流程:
- 如果没有异常发生,
try块中的所有代码正常执行后,程序会跳转到finally块,确保资源被关闭。
- 如果没有异常发生,
finally块的重要性:finally块中的代码保证了无论程序是否发生异常,都能执行清理操作,避免资源泄漏。- 它是处理资源释放(如关闭文件流、数据库连接等)的最佳位置。
通过这种方式,你可以帮助学员更好地理解异常处理流程,确保他们能够正确地使用 try、catch 和 finally 来处理代码中的异常,并管理资源。