第8天的笔记(异常)

    技术2022-05-14  7

       本来打算将异常一章结束掉,不过时间不够了(临近11:30),只能看到哪算哪,发了再说。明天补之,并开始新的一章——封装类。

    2011-05-23(Exception)1、异常的传播。异常是一个对象,某个方法(A)出现异常,这个异常会传递给调用这个方法的方法(B),这个方法有会把异常传递给调用它的方法(C),如此向上传递,知道main方法。即异常传递为:A—>B—>C—>main。注意,每个方法(包括main方法)接受到异常后都会抛出异常,这种现象称为异常再抛出。如下面代码:public class Test{ public static void main(String []args){ C(); System.out.println("OK"); } static void C(){ B(); System.out.println("OK"); } static void B(){ A(); System.out.println("OK"); } static void A(){ int []a=new int[3]; a[4]=1; System.out.println("OK"); } } 编译成功,运行结果为:                       Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4                       at Test.A(Test.java:16)                       at Test.B(Test.java:11)                       at Test.C(Test.java:7)                       at Test.main(Test.java:3)第十六行,数组下标溢出,产生数组下标越界异常,之后就层层传递。另外,由异常后面的代码:“System.out.println("OK");”无法进行,可看出java的代码执行顺序:先执行main,里面需调用C,执行C,里面需调用B,执行B,里面需调用A,执行A,A里面出现异常,之后往回传递。2、如果将代码改为如下: public class Test{ public static void main(String []args){ C(); System.out.println("OK1"); } static void C(){ B(); System.out.println("OK2"); } static void B(){ try {A();System.out.println("OK3");} catch(ArrayIndexOutOfBoundsException e){System.out.println("Catch successed");} System.out.println("OK4"); } static void A(){ int []a=new int[3]; a[4]=1; System.out.println("OK5"); } } 结果是:                                                          Catch successed                                                          OK4                                                          OK2                                                          OK1从“OK”的打印顺序看,异常往回传递到B方法,被捕获后B就想没发生异常一样照常进行,而后面的C、main也照常进行,所以按执行的顺序打印了“OK4”“OK2”“OK1”。3、将2代码第17行改为a[2]=1;即不出现异常。编译执行,结果为“OK5OK3OK4OK2OK1”,catch里面的语句没有执行。从这里和2可以看出:当出现异常,try里面代码不执行,如果没有try,更加是整个程序都不执行;如果没有异常,catch里面语句不执行。但是某种情况下,我想有无异常都要执行某段代码,当如何?(或者某人会钻牛角尖,说把这段代码往try、catch都放上即可。先不说这段必须执行的代码很长导致可读性差的问题,如果是try里面抛出了意料之外的异常呢,亦是不可)所以,必须有finally关键语句块用以放无论是否有异常都要执行的语句。当然,如下情况是不能执行finally里面的语句的:(1)finally本身有异常;(2)执行finally语句块地线程死亡;(3)finall中执行了System.exit(0);(4)断电;4、try、catch、finally之间要注意的问题:(1)catch必须紧跟try,同理,在没catch情况下,finally也必须紧跟try;(2)上面提到,catch、finally均可省略,但不可同时省略,即不能单有try语句;(3)try、catch、finally之间必须没有任何代码,注释除外。5、Exception类的子类中,除去RuntimeException类及其直接或间接子类,都称之为捕获异常,即必须处理的异常。如果写代码是不对塔进行处理,编译会出错。另外,如果try里面的不可能抛出某种捕获异常,catch又编写了该捕获异常的处理代码,编译也会出错。6、除了捕获异常,其他的异常都成为未捕获异常(Error类和Exception类及其子类),即不用必须处理异常。上面的数组下标越界异常属于此类,编译没错,运行会抛出这类异常。7、再抛出异常的分类——分显现再抛出和隐形再抛出。I、一旦某个方法可能会抛出捕获异常,则在方法声明之时必须特别指出。而通过编写代码将catch语句捕获的异常再次抛出,称显性再抛出。特别指出的语法:                                  访问限制 [static] 返回在类型 方法名(参数列表) throws 异常序列这个异常序列,每个异常之间用逗号隔开。对于捕获异常必须列出,未捕获异常,可列可不列。catch中,通过语法:                                                     throw 异常对象的引用将异常再抛出,throw只能跟一个异常对象的引用,注意这里的用词,是对象的引用,并且这个引用类型的决定了再抛出异常的类型,而非引用指向的对象。II、上面的1,也是再抛出异常,并无throws语句,编译也通过,这是为何?因为那是隐性再抛出,其与显性有如下异同:(1)若在抛出的异常是捕获异常,则隐性、显性都必须在方法题中声明;(2)显性再抛出是在方法体中使用throw语句抛出;(3)隐性再抛出是在方法体中无任何抛出语句,若产生则自动抛出。8、方法重写中的抛出异常。子类重写父类方法时,重写后的方法所抛出的异常范围必须小于等于父类的。等于好理解,就是抛出的异常类型与父类同;小于,就是重写后的方法抛出的异常是父类抛出异常的子类。 


    最新回复(0)