Throwable父类
Throwable是java中所有异常类的父类,其下有两个子类:Error和Exception。
其中,Error异常类主要是反映系统层面的错误,如虚拟机内存溢出、程序死锁等,用得比较少,一旦出现就说明程序彻底挂了。
Exception类用得比较多,主要是指当编码、环境、用户操作输入出错等问题出错时抛出的异常,其下有许多子类,可分为两类异常:非检查异常与检查异常。
非检查异常指的是“RuntimeException”,其下还有许多子类,出现原因可能是引用了一个空对象的属性或方法,数组访问越界、类型转换错误,还有可能是算术方面引起的一些异常等等。如下图:
引起检查异常的原因多种多样,如文件不存在、数据库连接错误等,与非检查异常不同,我们需要手动添加捕获以及处理异常的语句:
处理异常
在java中我们用“try.....catch”或“try.....catch....finally”来处理异常
try.....catch
语法:
发生异常时,try中语句停止执行,转而执行catch中的语句,而程序中的其他语句会继续正常执行。catch中的语句如何执行由程序人员决定。如:
可使用多重catch语句块来针对不同的异常:
书写多重catch语句块时,要注意先小后大,即先子类,后父类,如下:
因为出现异常时程序会就近寻找异常处理语句,而子类继承于父类,针对于父类的异常对于子类来说也是同样会发生的。
try.....catch....finally
如果当出现异常后还要进行一些“善后”的工作的话,就可以使用finally了,语法如下:
执行顺序为:先执行try,抛出异常后执行catch,如果有finally则再执行finally中的语句,然后就是try..catch..finally语句块之外的语句,最后回到主函数。(对于Exception类型的对象e,可以e.printStackTrace()方法来打印错误信息。)
异常抛出及自定义异常
用throw或throws来抛出异常
语法如下:
throws后面可以紧跟多种异常,多种异常之间用逗号隔开。throw则是写在方法体里面,表示抛出的动作。
如果某个方法调用了会抛出异常的方法,那么必须添加try..catch来捕获这种异常,或者添加throws声明来将异常抛出给更上一层的调用者去进行处理(如同工厂中出现了原料短缺的异常,这种异常员工无法自行处理,只能抛给更上一层的领导去处理),throw抛出异常后,后续程序不会再运行。如下:
以下是java类库中丰富的异常种类:
自定义异常
除了java类库中的异常,我们还可以自定义异常,自定义的异常必须继承于java类库中已有的异常类,或者继承于基类Exception,语法如下:
如下就是我们自定义的一个异常类:
异常链
有时候我们会再捕获一个异常,然后抛出另外一个新的异常,并且在新的异常中添加对原始异常的引用,希望把异常原始信息保存下来,这被称为异常链。比如以下例子:
test1用于抛出上面自定义的异常类DrunckException,在test2中调用了test1捕获异常,然后抛出另外一个异常,并将异常信息包装到RuntimeException中,然后抛出,main方法中打印错误信息,运行结果如下: