199. Java 异常 - 异常处理 “秘籍”:try、catch、finally 如何协同?

35 阅读3分钟

199. Java 异常 - 异常处理 “秘籍”:try、catch、finally 如何协同?


在前面的部分中,我们已经讨论了如何构建 trycatchfinally 代码块。在这一节中,我们将把这些概念结合在一起,分析 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 块。

正常执行流程:
  1. try 块中的代码执行完成,PrintWriter 对象成功创建,并写入文件。
  2. 执行到 finally 块时,PrintWriter 被关闭,确保资源得到释放。

输出示例(无异常时):

Entering try statement
Closing PrintWriter

解释:

  • Entering try statement:表示程序进入了 try 块并开始执行。
  • Closing PrintWriter:表示 PrintWriter 被成功创建并关闭,资源得到了释放。

🔑 关键点总结:

  1. 异常发生时的处理流程
    • 当异常发生时,程序会立即跳转到对应的 catch 块处理异常。
    • 处理完异常后,无论是否发生异常,finally 块的代码都会执行,用于释放资源。
  2. 正常执行的处理流程
    • 如果没有异常发生,try 块中的所有代码正常执行后,程序会跳转到 finally 块,确保资源被关闭。
  3. finally 块的重要性
    • finally 块中的代码保证了无论程序是否发生异常,都能执行清理操作,避免资源泄漏。
    • 它是处理资源释放(如关闭文件流、数据库连接等)的最佳位置。

通过这种方式,你可以帮助学员更好地理解异常处理流程,确保他们能够正确地使用 trycatchfinally 来处理代码中的异常,并管理资源。