8.1异常处理概述8.2异常处理机制8.3异常类8.4综合实例8.5习题8.1.1异常处理的概念异常是指在某些情况下,会使当前正在执行的方法或代码块无法继续进行的问题。异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。例如,代码中如果少了一个分号,那么运行出来结果是提示是错误java.lang.Error;而如果代码为System.out.println(8/0),用0做了除数,那么会会抛出java.lang.ArithmeticException的异常。【实例8-1】Exception.javapublicclassException{publicstaticvoidmain(String[]args){intdenominator=0;if(denominator!=0){intnumerator=8/denominator;}else{System.out.println(除数为零);}System.out.println(numerator);}}运行结果:程序说明:在这个实例中,不考虑异常的作用,因此为了避免除数为零,最好的做法就是进行一次判断if(denominator!=0),当除数不为零的时候才进入循环做除法,否则直接打印输出结果,这个时候被除数还没有声明,因此程序会出错,抛出java.lang.Error的异常。【实例8-2】Exception.javapublicclassException{publicstaticvoidmain(String[]args){intdenominator=0;intnumerator=8/denominator;System.out.println(numerator);}}运行结果:8.1.2使用异常处理的原因程序执行时经常会出现用户输入出错、所需文件找不到、运行时磁盘空间不够、内存耗尽无法进行类的实例化、算术运算错、数组下标越界、JVM崩溃等运行错误,影响程序的正常执行。错误及异常是不可避免的,一个好的应用程序,在满足用户要求的各种功能的同时,还应具备能预见程序执行过程中可能产生的各种异常的能力,并能为异常情况给予恰当处理。Java语言通过面向对象的异常处理机制来解决运行期间的错误,可以预防错误的程序代码或系统错误所造成的不可预期的结果发生。8.1.3方法的调用堆栈Java虚拟机用方法调用堆栈来跟踪每个线程中一系列的方法调用过程。每个线程都有一个独立的方法调用堆栈,堆栈底部的是程序的入口方法main(),放一个新的方法被调用时,java虚拟机就会把描述该方法的堆栈结构置入栈顶,位于栈顶的方法是正在执行的方法。Java对异常的处理主要涉及两方面的内容:一是抛出(throw)异常如果程序在运行过程中出现了运行错误,并且产生的异常与系统中预定义某个异常类相对应,系统就自动产生一个该异常类的对象,这个过程称为抛出(throw)异常。二是捕捉(catch)异常当有异常对象抛出时,将在程序中寻找处理这个异常的代码,如果找到处理代码,则把异常对象交给该段代码进行处理,这个过程称为捕捉(catch)异常。8.2.1捕获异常我们经常会遇见这样的情景:程序中出现了异常但是没有相应的处理措施。这时候java语言就会自动捕获并处理异常,一般来说表现为报告异常字符串,并且在异常发生出结束程序的运行。但是,为了更好的保证程序正常运行,需要人为的捕获并处理异常。在java语言中该机制的使用是try-catch-finally结构。try-catch-finally结构的一般格式如下:try{可能抛出异常的语句}catch(Exception1e){异常处理代码}catch(Exception2e){异常处理代码}finally{必需执行的代码}如果在程序中有效的设计了try-catch-finally结构,会出现两种情况:能够捕获到异常和不能捕获到异常。如果没有捕获到异常时,程序会跳过catch直接到finally(如图8-3没有捕获到异常时)如果捕获到某个异常,则进入相应的catch块内(如图8-4捕获到某个异常时)try{语句1;语句2;}catch(Exception1e){………}catch(Exception2e){………}finally{………}语句;try{语句1;语句2;}catch(Exception1e){………}catch(Exception2e){………}finally{………}语句;图8-3没有捕获到异常时图8-4捕获到某个异常时8.2.2声明异常try-catch-finally是在产生异常的方法内部处理异常。除此之外,还可以通过调用产生异常的方法来处理这些异常。在方法的声明中使用throws语句,其一般格式如下:返回类型方法名(参数)throws异常类型列表{方法体;}【实例8-5】ThrowsException.javapublicclassThrowsException{staticvoidtest(inta)throwsArithmeticException,ArrayIndexOutOfBoundsException{System.out.println(InSituation+a);if(a==0){System.out.println(noExceptioncaught);return;}elseif(a==1){intiArray[]=newint[4];iArray[10]=3;}}publicstaticvoidmain(Stringargs[]){//try-catch-finally结构try{test(0);test(1);}catch(ArrayIndexOutOfBoundsExceptione){System.out.println(Catch+e);}finally{System.out.println(inProcfinally);}}}运行结果:InSituation0noExceptioncaughtInSituation1Catchjava.lang.ArrayIndexOutOfBoundsException:10inProcfinally8.2.3抛出异常日常生活中,例如学校中有什么问题都会先去问老师,但是有一些问题例如转学是不能由老师来解决的,这时候老师就需要再去问校长,由校长来解决这个问题。可能校长还有不能解决的问题,就需要去问教育部。抛出异常也是这样的,当一个程序段发生异常时,如果自己不能够进行异常处理,就可以将抛出异常给上一层。如果上一层也不能解决就可以一直向上抛出异常,直到抛出给main方法。如果仍然不能解决,就会中断程序,将异常显示出来。在java语言中,所有方法都是通过throw语句来抛出一个异常事件,抛出异常首先需要通过throw语句生成一个异常类的对象,其一般格式如下:thrownew异常类名;注意:异常类名必须是Exception或其直接或间接子类。利用throw语句,可以自定义异常,并显示自定义的异常信息。【实例8-6】ThrowException.javaclassThrowException{publicstaticvoidmain(Stringargs[]){try{throwTest();}catch(NullPointerExceptione){System.out.println(Recaught:+e);}}staticvoidthrowTest(){try{thrownewNullPointerException(test);}catch(NullPointerExceptione){System.out.println(CaughtinsidethrowTest.);throwe;}}}运行结果:CaughtinsidethrowTest.Recaught:java.lang.NullPointerException:test8.2.4自定义异常尽管java内建的异常处理机制提供了丰富的异常类型,能够满足程序员的大部分需求,但有时候也需要程序员在程序中自定义异常类,根据自己的意愿来处理异常。自定义异常的一般格式为:class异常类名extendsException{方法体;}8.3.1java中异常类的结构在java语言中,异常有两种分类:1)java.lang.Throwable类为所有对象的父类,可以使用异常处理机制将这些对象抛出并捕获。2)在Throwable类中定义方法来检索与异常相关的错误信息,并打印显示异常发生的栈跟踪信息。它有Error和Exception两个基本子类:错误(Error):JVM系统内部错误、资源耗尽等严重情况;异常(Exception):其它因编程错误或偶然的外在因素导致的一般性问题。Throwable类Error类Exception类……RuntimeException类ArithmeticException类IndexOutofBoundException类ArrayIndexOutofBoundsException类……IoException类FileNotFoundException类EOFException类……在Java.lang包在Java.io包图8-5java中异常类的结构8.3.2运行时异常运行时异常(RuntimeException)是指因设计或实现方式不当导致的问题。也可以说是程序员的原因导致的问题,本来可以避免发生的情况。这种异常的特点是java编译器不会检查它。由于没有处理它,因此,当出现这类异常时,异常对象一直被传递到main()方法,程序将异常终止。如果采用了异常处理,异常将会被相应的程序执行处理。表8-1给出了java语言预定义的Error异常子类,下面是运行时异常的常见子类,如表8-2运行时异常子类:异常类名描述ArithmeticException算数错误NullPointerException非法使用空引用ArrayIndexOutOfBoundsException数组下标越界ClassCastException非法强制转换类型NegativeArraySizeException创建带负维数大小的数组的尝试ArrayStoreException数组元素赋值类型不兼容IndexOutOfBoundException某些类型索引越界NumberFormatException字符串到数字格式非法转换SecurityException试图违反安全性StringIndexOutOfBounds试图在字符串边界之外索引UnsupportedOperationException遇到不支持的操作IllegalArgumentException调用方法的参数非法IllegalMonitorStateException非法监控操作IllegalStateException环境或应用状态不正确IllegalThreadStateException请求操作与当前线程状态不兼容表8-2运行时异常子类8.3.3受检查异常Exception类中除了RuntimeException子类以外的类都是受检查异常类。如表8-3受检查异常子类:异常类名描述ClassNotFoundException找不到类CloneNotSupportedException试图复制一个不能实现的Cloneable接口对象NoSuchMethodException请求的字段不存在NoSuchMethodException请求的方法不存在InterruptedException一个线程被另一个线程中断IllAccessException对一个类的访问被拒绝InstantiationException试图创建一个抽象类或者抽象接口的对象【实例8-9】ExceptionTest.javaclassExceptionComextendsException{privatestaticfi