欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

理解异常一

程序员文章站 2022-04-16 12:17:10
...

一.异常简介 

Exception是"Exception Event"的简称.

 

当某个方法中产生了一个错误,这个方法将产生一个对象并传递给运行时系统.这个对象就叫做异常对象,它包含了错误的信息,它的类型以及发生错误时程序的运行状态.创建一个对象并把它传递给运行时系统的行为就叫做抛出异常(throwing an exception).

 

当异常发生后,运行时系统试图找到一个合适的异常处理器来处理这个异常.如何找呢?方法就是从异常发生的地方反向搜索调用栈(call stack),直到找到一个合适的处理器,那么我们说捕获了这个异常(catch the exception).什么才是一个合适的处理器呢?只要发生的异常与Catch块中声明的异常类型相同或者是其父类型,我们就说它是一个合适的处理器.如果在调用栈(call stack)中没有搜索到合适的异常处理器,运行时系统将会终止.

 

二.异常分类

第一种就是checked exception,是可预知的各种情况以及能迅速从错误中恢复过来的.例如,想象一个应用程序提示用户输入文件名,然后根据文件名构造一个java.io.FileReader对象,正常情况下,用户输入的是已经存在的并且可读的文件名,程序将会正常执行.然而当用户输入了一个错误的,不存在的文件名时,程序将会抛出一个java.io.FileNotFoundException 一个良好的程序就会提示出错了,让用户输入正确的文件名.

 

除了被Error,RuntimeException和它们的子类指明的,其余的Exception都是checked exception.是应用程序可以处理的异常.

 

 

第二种异常就是error,是应用程序不能预先知道并且恢复的.例如,当某个程序打开了一个文件作为输入,但是由于硬件或者操作系统出现故障,程序不能获取输入,那么将会抛出一个java.io.IOError.凡是被Error或其子类指定的就是error.

 

 

第三种就是runtime exception,就是那些程序不能预知的的内部错误.比如说程序的bugs,逻辑上的错误,或者错误的使用了API等.凡是被RuntimeException或其子类指定的就是runtime exception.

 

error和runtime exception都叫做unchecked exception.

 

三.捕获和处理异常

这个部分讲解如何使用异常处理组件(try,catch,finnally)来编写一个异常处理器.

 

下面的例子定义了一个ListOfNumbers类.在构造方法中创建了一个ArrayList对象,用于存放一个从0-9的数字列表.并定义了一个writeList方法,用于将数字列表输出到一个叫OutFile.txt的文本文件中.

 

//Note: 这个类故意被设计成不能被编译的
import java.io.*;
import java.util.List;
import java.util.ArrayList;

public class ListOfNumbers {

  private List<Integer> list;
  private static final int SIZE = 10;

  public ListOfNumbers () {
    list = new ArrayList<Integer>(SIZE);
      for (int i = 0; i < SIZE; i++) {
        list.add(new Integer(i));
    }
  }

  public void writeList() {
    PrintWriter out = new PrintWriter(
      new FileWriter("OutFile.txt"));

    for (int i = 0; i < SIZE; i++) {
      out.println("Value at: " + i + " = " + list.get(i));
    }
    out.close();
  }
}
 

 

new FileWriter("OutFile.txt"));

这行代码调用了一个构造方法用于初始化一个输出流,如果文件不能被打开,这个构造方法将会抛出一个 IOException.

 

 

out.println("Value at: " + i + " = " + list.get(i));

这行代码调用了ArrayList的get方法,如果传给它的参数太小或者太大都会抛出一个IndexOutOfBoundsException.

 

 

如果你想编译这个类,编译器将会打印出关于FileWriter抛出的异常信息,而不会打印get方法抛出的异常信息.原因是IOException是一个checked exception, IndexOutOfBoundsException 是一个unchecked exception.

 

 

 

try块:

第一步就是将可能抛出异常的代码封装在一个try块中.

     try{

          code

     }

     catch块和finnally块

 

你可以在每行可能抛出异常的代码外加上一个try,catch块,也可以在多行中只使用一个try,catch块.本例中使用的第二种方式.

 

private List<Integer> list;
private static final int SIZE = 10;

PrintWriter out = null;

try {
    System.out.println("Entered 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 and finally statements . . .


 catch块:

通过直接在try块之后增加一个或者多个catch块来与try块进行关联,在try块和第一个catch块之间不能有任何其他代码.

try {

} catch (ExceptionType name) {

} catch (ExceptionType name) {

}

 没一个catch块都是一个异常处理器,用来处理其参数指明的异常类型或其子类型.

如果异常处理器被调用,改catch块中的代码将会执行.

 

下面是两个writeList方法的两个异常处理器

try {

} catch (FileNotFoundException e) {
    System.err.println("FileNotFoundException: "
                        + e.getMessage());
    throw new SampleException(e);

} catch (IOException e) {
    System.err.println("Caught IOException: "
                        + e.getMessage());
}

 两个异常处理器都打印错误消息,第二个出了这个什么也不做,只是让程序继续执行.第一个处理器打印错误消息并抛出一个用户自定义异常.在这个例子中,如果FileNotFoundException被捕获将会倒值SampleException被抛出,如果你想让你的程序在这种情况下用一种特定的方式处理,那么你也可以这么做.

 

异常处理器不仅仅能打印错误信息和终止程序,还可以从错误中恢复,提示用户,或者通过exception链传到更高级别的处理器去处理.

 

在一个处理器中捕获多个异常:

在java7中,一个catch块中可以处理不止一种异常.这个特性使得我们可以减少很多重复代码.多个exception用

"|"分隔.

catch (IOException|SQLException ex) {
    logger.log(ex);
    throw ex;
}

 注意:如果使用这种方式,ex将是final的,你不能在catch块中给它赋值.