读书人

详解 错误exception(一)

发布时间: 2013-04-05 10:24:33 作者: rapoo

详解 异常exception(一)
Exception

java程序使用exception处理errors和别的异常事件。

1:什么是异常:

异常是指在程序执行期间,打乱了正常的程序指令流而出现的异常事件。

exception是 excepitonal event 的 速记。

当方法中出现一个错误的时候,这个方法会创建一个对象切换到正在运行的系统,这个对象 叫做异常(exception)对象,异常对象中包含了出现错误的信息,异常的类型,以及此时运行程序的状态。创建一个异常对象在运行时系统中处理它的过程叫做抛出一个异常。

当一个方法抛出一个异常后,这个运行时系统尝试着去找处理这个异常的方式,这个一系列处理异常的方式是一系列顺序的方法调用的 列表,这个方法列表叫做调用栈。

详解 错误exception(一)

上图是调用的方法栈。

运行时系统搜索调用栈,找一个包含这个异常处理代码块的方法。这段代码块叫做异常处理程序(exception handler),搜索的顺序是:从这个错我出现的方法开始,依次进行处理,这个顺序是方法调用的反顺序,例如以上调用栈---是从上到下查找的顺序。当合适的处理程序被找到,运行时系统传递这个异常到异常处理程序,异常处理程序考虑合适是根据抛出异常对象的类型和这个处理程序的类型匹配。


这个异常处理程序被选择叫做 捕获一个异常,如果运行时系统搜索调用栈中所有的方法但是没有找到合适的异常处理程序,这个运行时系统将终止。

详解 错误exception(一)

上图为搜索调用栈找对应的异常处理程序的过程

2:异常的分类:一:异常处理方式java语言提供两种处理异常的方式:1:try语句捕获一个异常,try必须提供一个异常的处理。2:一个方法指定抛出一个异常,方法必须提供throws语句列出需要抛出的异常,相当于方法抛出一个指定的异常。并不是所有的异常都是需要捕获或者特定的抛出的,为了理解这句话,看三种不同的异常分类。
二:异常的三种类型1:检测性异常(Checked Exception):
一些写的好的程序应该提前考虑到这些异常,这种异常通常出现在写好的程序的内部,应用程序能够提前预测覆盖和捕获这种异常并从中恢复。例如:假设一个应用程序中需要用户输入文件名,然后通过传递这个文件名字到java.io.FileReader类中的构造方法中 打开这个文件,正常情况下,用户提供存在的文件名称,可读性的文件,因此FileReader的对象能够构造成功,这个应用程序能够正常的执行,但是有时用户提供了不存在的用户名称, 这个构造方法会抛出一个FileNotFoundException,一个好的应用程序应该捕获这个异常,通知用户这个错误,有可能提示输入正确的文件名。检测性异常是Catch or Specify Requirement主题,除了Error , RuntimeException以及它们的子类,所有的其他异常都是检测性异常(Checked Exception)。2:error第二种异常是error,这种异常通常出现在应用程序的外部,不能够进行提前预测和从中恢复。例如,假设一个应用程序成功的打开一个文件,但是因为硬盘或者系统故障问题,会出现读取文件不成功将抛出一个java.io.IOError,应用程序可能为了通知用户出现了问题选择捕获这个异常,但是打印一个堆栈信息并退出也许会更有意义。Errors不是Catch or Specify Requirement的主题,Error是一种异常表示Error和它的子类。3:运行时异常第三种异常时运行时异常,这种异常时应用程序的内部的异常,应用程序通常不能够预测和从中恢复。这通常表明程序的bug,例如逻辑错误或者不正确的使用了API等,例如考虑上面的传递文件名到java.io.FileReader类的构造方法中创建对象的FileReader对象的例子,如果因为逻辑错误传递给构造方法一个null,构造方法将抛出一个NullPointException空指针异常,应用程序能够捕获这个异常,但是消除出现异常的这个bug也许更有意义。运行时异常不是一种Catch or Specify Requirement的主题。运行时异常显示RuntimeException以及它的子类。
Error和runtime exception(运行时异常) 都叫做非检测性异常(unchecked exceptions)。

一些程序员认为 Catch or Specify Requirement是一种有严重缺陷的异常机制,想通过使用unchecked exception 代替 checked exception,通常是不建议。

3:捕获处理异常1:解释异常这一小节描述如何使用try ,catch,finally语句块去实现异常处理程序处理,在Java SE 7 中也介绍了 try-with-resources语句,try-with-resources特别适用于关闭使用的资源,例如流。下列例子定义和实现了ListOfNumbers类,当构造的时候,包含了一个ArrayList---包含0-9是个Integer元素,这个类也定义了一个writeList方法,写这些数字进入Output.txt文件中:例子如下:
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 + " = " + vector.elementAt(i));                      } catch (ArrayIndexOutOfBoundsException e) {        System.err.println("Caught ArrayIndexOutOfBoundsException: "                           +  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");        }    }}

两种执行情况:第一种执行期间抛出异常:创建FileWriter对象失败有很多原因,如果程序不能创建或者写入显示的文件,将会抛出一个IOException异常,当FileWriter抛出一个异常的IOException的时候,运行时系统立刻停止try块的执行,调用的方法不完全执行了,运行时系统开始调用方法调用栈的顶端找到合适匹配的异常进行处理,在这个例子中,当IOException出现的时候,FileWriter构造方法在调用战斗顶端,但是FileWriter没有一个合适的异常处理程序,因此运行时系统检查下一个方法,即writeList方法,在这个方法的调用栈中,writeList方法有两个异常处理程序,一个IOException和一个IndexOutOfBoundsException,运行时系统顺序的检测在try语句块后出现的catch种类,第一个处理程序的参数类型是IndexOutOfBoundsException,这和抛出的异常不匹配,因此运行时系统检测下一个异常处理程序---IOException,运行时系统找到了匹配的异常处理程序,catch块中的代码被执行。
异常处理程序执行完毕后,运行时系统传递控制到finally块,不管catch是否被调用,finally块中的代码执行。在这个例子中FileWriter从来没有打开,因此不需要继续关闭,当finally执行完毕后,程序继续执行finally块后的第一个语句。以下是抛出IOException的输出:
Entering try statementCaught IOException: OutFile.txtPrintWriter not open 
另外一种情况try块正常结束:这种情况下所有的语句成功执行没有异常发生,执行完try块以后,运行时系统传递控制到finally块,因为所以的都是成功执行,PrintWriter是打开的,当执行到finally时,关闭PrintWriter关闭,再一次的,finally块完成执行,程序继续执行finally块结束后的语句块,下面是没有抛出异常的执行结果:
Entering try statementClosing PrintWriter










读书人网 >编程

热点推荐