前面的章节描述了怎么在ListOfNumbers类的writeList方法里面构建try,catch和finally代码块。现在,我们把所有代码块串起来,看看会发生什么。

当所有的组件放在一块,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代码块有三种不同的退出可能性;下面是其中两种:
  1. try语句失败并抛出一个异常。这个异常有可能是new FileWriter语句抛出的IOException异常,也有可能是for循环里面因为一个错误的索引值引发的IndexOutOfBoundsException异常。
  2. 一切正常,try语句正常退出。

让我们看看writeList方法分别在这两种退出情况下发生了什么。

场景1:发生了一个异常

有很多原因可能导致FileWriter创建失败。比如,可能因为程序无法创建或改写这个文件,致使FileWriter的构造器抛出一个IOException异常。

当FileWriter抛出一个IOException异常,运行时系统立马停止执行try代码块;方法调用执行的不完全。然后,运行时系统开始从方法调用栈的顶部开始搜索合适的异常处理器。在这个例子中,当IOException异常发生了,FileWriter的构造器方法就是调用栈的顶部。然而,在FileWriter的构造器方法内部没有一个合适的异常处理器,所以运行时系统会在方法调用栈中检查下一个方法——writeList方法。writeList方法有两个异常处理器:一个处理IOException,一个处理IndexOutOfBoundsException。

运行时系统按照出现的顺序检查writeList方法的处理器。第一个异常处理器的参数是IndexOutOfBoundsException。它不能匹配抛出的异常类型,所以运行时系统检查下一个异常处理器——IOException。这个处理器能匹配抛出的异常类型,所以运行时系统结束搜索。现在运行时系统已经找到了合适的异常处理器,那个catch代码块的代码将被执行。

在异常处理器执行完以后,运行时系统把控制转移到finally代码块。无论上面捕获了什么异常,finally代码块里面的代码一定会执行。在这个场景中,FileWriter从来没有被打开过,所以没必要关闭。当finally代码块执行完,将继续执行finally代码块后面的代码。

当ListOfNumbers程序抛出IOException异常的时候,将会输出:

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代码块。因为一切顺利,所以PrintWriter被打开了,当控制到达finally代码块,将会关闭PrintWriter。再次说明,当finally代码块执行完,将继续执行finally代码块后面的代码。

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





原文地址