1第6章Java例外处理本章要点通过本章的学习,主要了解例外的概念,作用和例外的产生,掌握怎样捕捉例外,怎样创建自己的例外类,以及怎样利用Java开发环境提供的例外类来处理程序中的例外。通过技能训练,掌握Java语言中例外处理的基本技术。6.1概述例外就是在程序运行时由代码所产生的不正常状态。换句话说,例外就是一个运行错误。在不支持例外处理的计算机语言中,错误必须由人工进行检查和处理,这显然麻烦而低效。Java语言提供了例外处理机制,为方法的例外终止和出错处理提供了清楚的接口。例外(exception)也是例外事件(exceptionalevent)的简称,它是在程序运行中出现的违背正常流向的事件。许多不同种类的错误可以导致例外,从严重的硬件错误到简单的编程错误。当在Java方法中发生这样的错误时,方法将创建一个例外对象,并把它交给运行系统处理,运行系统负责找到处理错误的代码并执行之。例外对象包括例外的信息、类型和错误发生时程序的状态以及对该错误的详细描述。在Java中,创建一个例外对象并把它送到运行系统叫做抛弃例外。在抛弃例外后,运行系统将寻找合适的方法来处理例外。如果产生的例外类与所处理的例外一致,则认为找到了合适的例外处理方法。如果运行系统找遍了所有方法而没有找到合理的例外处理方法,则运行系统将终止Java程序的运行。例外处理也叫做捕捉例外。Java中的每个例外都是一个对象,它是java.lang包中Throwable类或其子类的实例对象。Throwable类有两个子类:Exception类和Error类。Exception类是可以被捕捉并且可能恢复的例外类,也可以继承Exception类生成自己的例外类。Error类一般被认为是不可恢复和不可捕捉的例外类。26.2例外的的类型图6.1例外类的层次6.2.1例外类的层次结构Java语言用继承的方式来组织各种例外。所有的例外都是Throwable类或子类,而Throwable类有直接继承于object类。Throwable类有两个子类Error类与Exception类。Exception类又进一步细分为RuntimeException(运行时例外)类和Non-RuntimeException(非运行时例外)类。图6.1显示了个例外之间的继承关系。如果程序中可能产生非运行时例外,就必须明确地加以捕捉并处理,否则就无法通过编译检查。与非运行例外不同的是,错误(Error)与运行例外(RuntimeException)不需要程序明确地捕捉并处理。6.2.2Exception类及其子类Exception类分为RuntimeException(运行时例外)类和Non-RuntimeException(非运行是例外类)类。1.运行时例外运行时例外表现在Java运行系统执行过程中的例外,它是指Java程序在运行时发现的由Java解释抛弃的各种例外,包括算术例外,下标例外等等。表6.1列出几种常见的例外。表6.1几种常见的运行时例外例外类名功能说明ArithmeticException除数为零的例外IndexOutOfBoundsException下标越界例外ArrayIndexOutOfBoundsException访问数组元素的下标越界例外StringIndexOutOfBoundsException字符串下标越界例外ClassCaseException类强制转换例外Java.lang.ObjectJava.lang.ThrowableJava.lang.ErrorJava.lang.Exception各种错误子类Java.lang.RuntimeExceptionJava.lang.Non_RuntimeException各种运行异常子类各种非运行异常子类3NullpointerException当程序试图访问一个空数组中的元素,或访问一个空对象中的方法或变量时产生的例外2.非运行是例外非运行是例外是由编译器在编译时检测是否会发生在方法的执行过程中的例外。非运行例外是Non-Runtimeexception及其子类的实例,可以通过throws语句抛弃。Java在其标准包Java.lang、java.util、java.io、java.net中定义的例外类都是非运行时例外类。表6.2列吃了常见的非运行时例外。表6.2非运行例外例外类名功能说明ClassNotfoundException指定类或接口不存在的例外IllegalAccessException非法访问例外IOException输入输出例外FileNotFoundException找不到指定文件的例外ProtocolException网络协议例外SocketExceptionSocket操作例外MalformedURLException统一资源定位器(URL)的格式不正确的例外6.2.3Error类及其子类Error类定义了正常情况下不希望捕捉的错误。在捕捉Error子类时要多加小心,因为它们通常在出现灾难性错误时被创建。表6.3列出一些常见的Error例外类。表6.3Error例外类例外类名功能说明LinkageError动态链接失败VirtualMachineError虚拟机错误AWTErrorAWT错误6.3Java例外产生于捕捉6.3.1产生例外通过下面两个引例来认识例外的产生。引例1importjava.io.*;classException1{publicstaticvoidmain(Stringargs[]){FileInputStreamfis=newFileInputStream(text);intb;while((b=fis.read())!=-1){System.out.print((char)b);}4fis.close();}}该引例的第6行表明在一个文件“text”上建立文件输入流。运行此程序时,如果这个文件并不存在,就会产生例外。另外,第8行是读此文件的内容,如果该文件不存在,则从此文件中读取数据时,也可能发生例外。引例2classException2{publicstaticvoidmain(Stringargs[]){inta=0,b=0;a=36/b;System.out.println(a=+a);}}从该引例的第6行不难看出,除数为零。因此,运行此程序时必然会发生除零溢出的例外事件,使程序无法继续运行。上面的两个引例都有或可能有例外产生。对于一些例外,在程序中必须对它进行处理,否则编译程序时会指出错误,如引例1;但对另一些例外,在程序中可以不做处理,而直接由运行系统来处理,如引例2。6.3.2捕捉例外一个方法中如果对某种类型的例外对象提供了相应的处理代码,则这个方法就可以捕捉对应的例外。捕捉例外就是通过try-catch-finally语句实现的。其语法为try{正常程序段,可能抛弃例外;}catch(例外类1例外变量){捕捉例外类1有关的处理程序段;}catch(例外类2例外变量){捕捉例外类2有关的处理程序段;}┇finally{退出例外处理程序段;}1.try用来监视所在的程序块是否发生例外,如果发生例外就抛弃它。对于系统产生的例外或程序块中未用try监视所产生的例外,将一律被Java运行系统自动抛弃。2.catch5用来捕捉try程序块中所抛弃的例外,并根据例外类型采取相应的方法进行处理,每个try程序块后面紧接着一个或多个catch语句,用于捕捉try程序块中所抛弃的一个或多个例外。catch语句只需要一个形式参数,参数类型给出它能够捕捉的例外类型,这个类必须是Throwable的子类,运行时系统通过参数值把被抛弃的例外对象传递给catch块,在catch快中时对例外对象进行处理的代码。例6.1捕捉引列1中的例外。importjava.io.*;classException3{publicstaticvoidmain(Stringargs[]){try{FileInputStreamfis=newFileInputStream(text);intb;while((b=fis.read())!=-1){System.out.print((char)b);}fis.close();}catch(FileNotFoundExceptione){System.out.print(e);}catch(IOExceptione){System.out.print(e);}}}这里使用了两个catch语句分别对try代码块中可能出现的两个例外事件进行处理。第一种情况,如果要打开的文件“text”在当前目录中不存在,程序运行时会抛弃一个FileNotFoundException例外对象,由于第一个catch语句与该例外类型匹配,所以程序将执行第一个catch语句,于是就会显示下面的信息:java.io.FileNotFoundException:text(系统找不到指定文件。)一般地,程序中如果有多个catch语句,那么,若有一个catch语句的例外与抛弃的例外对相匹配,那么,此catch语句将被执行,其他catch语句将被忽略。此例中,由于第一个catch语句首先得到匹配,第二个catch语句将不会被执行。因此在安排catch语句的顺序时,首先应该捕捉最特殊的例外,然后再逐渐一般化。通常在指定所捕捉的例外类型时,应该避免选择最一般的类型(如Exception)。否则,当例外事件发生时,程序中不能确切判断异常的具体类型并做出相应处理以从错误中恢复。第二种情况,如果要打开的文件“text”在当前目录中存在,程序的运行结果会显示“text”文件中的内容。3.Finally捕捉例外的最后一步是通过finally语句为例外吃力提供一个统一的出口,使得在控制流转到程序的其他部分以前,能够对程序的状态作统一的管理。不论在try代码块中是否发6生了例外事件,finally代码块中的语句都会被执行。例6.2finally语句语句作用。importjava.io.*;classException4{publicstaticvoidmain(Stringargs[])throwsIOException{FileInputStreamfis=null;try{fis=newFileInputStream(text);System.out.println(text文件的内容是:);intb;while((b=fis.read())!=-1){System.out.print((char)b);}}catch(FileNotFoundExceptione){System.out.print(e);}catch(IOExceptione){System.out.print(e);}finally{if(fis!=null){System.out.println(正在关闭文件…);fis.close();}else{System.out.println(文件没有打开!);}}}}如果要打开的文件“text”在当前目录中不存在,程序的运行结果如下:java.io.FileNotFoundException:text文件没有打开!这种情况下,finally语句被执行。如果要打开文件“text”在当前目录中存在,且“text”文件中的内容为:“letusbeginlearnjava.”,则程序的运行结果如下:text文件的内容是:letusbeginlearnjava.正在关闭文件...这种情况下,finally语句仍被执行。74.抛弃例外:throwthrow语句明确地抛弃一个例外。throw语句的一般格式:throw例外对象实例;其中例外对象实例必须是Throwable类或其子类的一个对象,简单数据不能用于例外。throw语句会中断程序流的执行,其后的语句将不会被执行。系统会检测离throw最近的try块,看是否存在与throw语句抛弃的例外类型相匹配的catch语句。如果找到匹配的catch语句,则