当前位置:   article > 正文

Java Catching and Handling Exceptions

Java Catching and Handling Exceptions

一、Catching and Handling Exceptions

本节描述如何使用三个异常处理程序组件(try、catch和finally块)来编写异常处理程序。然后,解释JavaSE7中引入的try-with-resources语句。try-with-resources语句特别适合于使用Closeable资源(如流)的情况。
本节的最后一部分将介绍一个示例,并分析在各种场景中发生的情况。
下面的示例定义并实现了一个名为ListOfNumbers的类。构造时,ListOfNumbers创建一个ArrayList,其中包含10个Integer元素,其顺序值为0到9。ListOfNumbers类还定义了一个名为writeList()的方法,该方法将数字列表写入名为OutFile.txt的文本文件。该示例使用java.io中定义的输出类,这些类在基本I/O部分中介绍。

  1. // Note: This class will not compile yet.
  2. import java.io.*;
  3. import java.util.List;
  4. import java.util.ArrayList;
  5. public class ListOfNumbers {
  6. private List<Integer> list;
  7. private static final int SIZE = 10;
  8. public ListOfNumbers () {
  9. list = new ArrayList<>(SIZE);
  10. for (int i = 0; i < SIZE; i++) {
  11. list.add(i);
  12. }
  13. }
  14. public void writeList() {
  15. // The FileWriter constructor throws IOException, which must be caught.
  16. PrintWriter out = new PrintWriter(new FileWriter("OutFile.txt"));
  17. for (int i = 0; i < SIZE; i++) {
  18. // The get(int) method throws IndexOutOfBoundsException, which must be caught.
  19. out.println("Value at: " + i + " = " + list.get(i));
  20. }
  21. out.close();
  22. }
  23. }

粗体的第一行是对构造函数的调用。构造函数初始化文件上的输出流。如果无法打开文件,构造函数将引发IOException。第二个粗体行是对ArrayList类的get方法的调用,如果其参数的值太小(小于0)或太大(大于ArrayList当前包含的元素数),则该方法抛出IndexOutOfBoundsException。
如果尝试编译ListOfNumbers类,编译器将打印关于FileWriter构造函数引发的异常的错误消息。然而,它不会显示关于get()引发的异常的错误消息。原因是构造函数IOException引发的异常是已检查的异常,而get()方法IndexOutOfBoundsException抛出的异常是未检查的异常。
既然您已经熟悉了ListOfNumbers类,并且可以在其中抛出异常,那么就可以编写异常处理程序来捕获和处理这些异常。

二、The Try Block

 构造异常处理程序的第一步是将可能引发异常的代码封装在try块中。通常,try块如下所示:

  1. try {
  2. code
  3. }
  4. catch and finally blocks . . .

示例中标记代码的段包含一行或多行合法的代码,这些代码可能会引发异常。(catch和finally块将在接下来的两个小节中解释。)

  1. private List<Integer> list;
  2. private static final int SIZE = 10;
  3. public void writeList() {
  4. PrintWriter out = null;
  5. try {
  6. System.out.println("Entered try statement");
  7. out = new PrintWriter(new FileWriter("OutFile.txt"));
  8. for (int i = 0; i < SIZE; i++) {
  9. out.println("Value at: " + i + " = " + list.get(i));
  10. }
  11. }
  12. catch and finally blocks . . .
  13. }


要从ListOfNumbers类中为writeList()方法构造异常处理程序,请将writeList.()方法的异常引发语句封装在try块中。有多种方法可以做到这一点。您可以将可能引发异常的每一行代码放在其自己的try块中,并为每一行提供单独的异常处理程序。或者,您可以将所有writeList()代码放在单个try块中,并将多个处理程序与之关联。下面的列表对整个方法使用一个try块,因为所讨论的代码非常短。

如果在try块中发生异常,则该异常由与其关联的异常处理程序处理。要将异常处理程序与try块相关联,必须在其后面放置catch块;下一节“catch Blocks”将向您展示如何进行。

三、The Catch Blocks

通过在try块之后直接提供一个或多个catch块,可以将异常处理程序与try块相关联。在try块的末尾和第一个catch块的开头之间不能有代码。

  1. try {
  2. } catch (ExceptionType name) {
  3. } catch (ExceptionType name) {
  4. }

每个catch块都是一个异常处理程序,用于处理由其参数指示的异常类型。参数类型ExceptionType声明处理程序可以处理的异常类型,并且必须是从Throwable类继承的类的名称。处理程序可以引用名为的异常。
catch块包含在调用异常处理程序时执行的代码。当处理程序是调用堆栈中ExceptionType与引发的异常类型匹配的第一个处理程序时,运行时系统调用异常处理程序。如果抛出的对象可以合法地分配给异常处理程序的参数,则系统将其视为匹配。
下面是writeList()方法的两个异常处理程序:

  1. try {
  2. } catch (IndexOutOfBoundsException e) {
  3. System.err.println("IndexOutOfBoundsException: " + e.getMessage());
  4. } catch (IOException e) {
  5. System.err.println("Caught IOException: " + e.getMessage());
  6. }

异常处理程序可以做的不仅仅是打印错误消息或暂停程序。它们可以执行错误恢复,提示用户做出决策,或者使用链接异常将错误传播到更高级别的处理程序,如“链接异常”部分中所述。

四、Multi-Catching Exceptions

 使用多捕获模式,可以使用一个异常处理程序捕获多个类型的异常。
在JavaSE7和更高版本中,单个catch块可以处理多种类型的异常。此功能可以减少代码重复,并减少捕获过宽异常的诱惑。
在catch子句中,指定块可以处理的异常类型,并用竖线(|)分隔每个异常类型:

  1. catch (IOException|SQLException ex) {
  2. logger.log(ex);
  3. throw ex;
  4. }

注意:如果catch块处理多个异常类型,则catch参数隐式为final。在本例中,catch参数ex是final,因此不能在catch块中为其分配任何值。

五、The Finally Block

当try块退出时,finally块始终执行。这确保即使发生意外异常,也会执行finally块。但finally不仅仅用于异常处理——它允许程序员避免返回、继续或中断意外绕过清理代码。将清理代码放在finally块中始终是一种良好的实践,即使预期没有异常。

注意:如果JVM在执行try或catch代码时退出,则finally块可能不会执行。

您在这里使用的writeList()方法的try块将打开PrintWriter。程序应在退出writeList()方法之前关闭该流。这带来了一个有点复杂的问题,因为writeList()的try块可以以三种方式之一退出。 

  1. 新的FileWriter语句失败,并引发IOException。
  2. get(i)语句失败,并引发IndexOutOfBoundsException。
  3. 一切成功,try块正常退出。 

运行时系统始终在finally块中执行语句,而不管try块中发生了什么。因此,它是执行清理的完美场所。
下面的writeList()方法的finally块将清理,然后关闭PrintWriter。

  1. finally {
  2. if (out != null) {
  3. System.out.println("Closing PrintWriter");
  4. out.close();
  5. } else {
  6. System.out.println("PrintWriter not open");
  7. }
  8. }

 要点:finally块是防止资源泄漏的关键工具。关闭文件或以其他方式恢复资源时,请将代码放在finally块中,以确保始终恢复资源。
在这些情况下,请考虑使用try-with-resources语句,该语句会在不再需要时自动释放系统资源。try with resources语句部分包含更多信息。

Java Catching and Handling Exceptions(二) 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/44577
推荐阅读
相关标签
  

闽ICP备14008679号