放在一起

前面的部分描述了如何为ListOfNumbers类中的writeList方法构造trycatchfinally代码块。现在,让我们遍历代码并研究可能发生的情况。

当所有组件放在一起时,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");
        }
    }
}

如前所述,此方法的try块具有三种不同的退出可能性:这是其中两个。

  • try语句中的代码失败,并引发异常。这可能是new FileWriter语句引起的IOExceptionfor循环中的错误索引值导致的IndexOutOfBoundsException

  • 一切成功,并且try语句正常退出。

让我们看看在这两种退出可能性期间writeList方法中发生了什么。

情况 1:发生异常

创建FileWriter的语句可能由于多种原因而失败。例如,如果程序无法创建或写入指示的文件,则FileWriter的构造函数将引发IOException

FileWriter抛出IOException时,运行时系统立即停止执行try块;正在执行的方法调用未完成。然后,运行时系统开始在方法调用堆栈的顶部搜索适当的异常处理程序。在此示例中,当发生IOException时,FileWriter构造函数位于调用堆栈的顶部。但是,FileWriter构造函数没有适当的异常处理程序,因此运行时系统会检查方法调用堆栈中的下一个方法writeList方法。 writeList方法具有两个异常处理程序:一个用于IOException和一个用于IndexOutOfBoundsException

运行时系统按照writeList的处理程序在try语句之后出现的 Sequences 检查它们。第一个异常处理程序的参数为IndexOutOfBoundsException。这与引发的异常类型不匹配,因此运行时系统将检查下一个异常处理程序IOException。这与引发的异常类型匹配,因此运行时系统结束了对适当异常处理程序的搜索。现在,运行时已找到合适的处理程序,该catch块中的代码将被执行。

异常处理程序执行后,运行时系统将控制权传递给finally块。 finally块中的代码将执行,无论其上方catch的异常如何。在这种情况下FileWriter从未打开过,也不需要关闭。 finally块完成执行后,程序 continuefinally块之后的第一条语句。

这是引发IOException时出现的ListOfNumbers程序的完整输出。

Entering try statement
Caught IOException: OutFile.txt
PrintWriter not open

以下清单中的粗体代码显示了在这种情况下执行的语句:

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");
        }
    }
}

情况 2:try 块正常退出

在这种情况下,try块范围内的所有语句都将成功执行,并且不会引发任何异常。执行从try块的末尾开始,运行时系统将控制权传递给finally块。因为一切都成功,所以当控制到达finally块时,PrintWriter打开,该块关闭PrintWriter。同样,在finally块完成执行之后,程序将 continuefinally块之后的第一条语句。

这是未引发任何异常时ListOfNumbers程序的输出。

Entering try statement
Closing PrintWriter

以下示例中的粗体代码显示了在这种情况下执行的语句。

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");
        }
    }
}