在java中,异常机制用的比C++频繁,但是一直没有比较系统完整地对java的异常机制作总结,使用异常的过程中总有点心里没底的感觉,这次进行一次相对完整的总结
首先是java的异常机制继承体系:
Java的异常机制分成两大类:error(错误)和exception(异常),这两大类都继承于一个父类Throwable。
error(错误):一般是指虚拟机运行时关于虚拟机的报错,比较常见的是内存不足错误OutOfMemoryErro,还有类定义错误NoClassDefFoundError。
exception(异常):异常类的子类又分成两大类:
一个是RuntimeException(运行时异常)和其子类,属于不检查异常,什么意思呢,就是说不用明显地进行捕捉和抛出声明就可以通过编译,也就是说这种异常java默认是不需要进一步处理的,那大家会有问,照这种做法,一层层往上抛不就会结束了整个程序的运行了吗?是的,这也就是java希望得到的效果,为什么,因为这种异常是编码的逻辑错误引起的,对程序业务而言是致命的,所以java更希望用这种严重的后果提醒你及时修改代码,而不是进行捕捉处理。一般常见的运行时异常有NullPointerException,ArithmeticException,ArrayIndexOutOfBoundException
另一个是非运行时异常,也就是编译异常,属于可查异常,什么意思,就是如果出现这类异常,java倾向你去捕获处理异常,如果你不明显得捕获异常或者声明往上层抛出异常,那么编译都通不过。这种异常一般是jdk应用类层级异常类或者是用户自定义异常类。比如IOException、SQLException,这种可以明显看出是应用层级的异常类。所以编译异常应该进行捕获处理以免导致应用级别的不确定性故障。
了解了上面的异常机制继承体系,以后见到各种异常类就能做到心里有底。知道该怎么处理。网上有句话我觉得总结的很好:总体来说,Java规定:对于可查异常必须捕捉、或者声明抛出。允许忽略不可查的RuntimeException和Error。
原因就是后者是非常严重的并且绝大部分情况下不是使用者所希望得到的后果,越早发现解决越好。
其次是异常处理过程语句一些需要注意的地方:
try、catch 和 finally大家都比较熟,不再讲普通语法了,而是强调下注意点:
1. Try后面必须跟cath和finally至少一个。是的,后面直接跟finally而没有cath也是可以
2. Finally正常情况下是必须执行的,并且在return语句返回前执行,除非在执行Finally前程序挂掉了。这个以前我以前一个误区,希望大家注意
3. Throw异常链是从方法调用栈递归网上传递的,如果一直到main函数都没处理就会使整个程序进程终止
4. 在跑完捕获语句中就算对子类异常对象的引用就算用父类名进行强制转换,再抛出是会被后续的子类捕获语句所捕获的,原因就是java中对引用类型的转换不会影响所引用真正对象类型,所以还是会被后续子类异常捕获语句捕获。
5. 还有一个是之前不知道的一个知识点所有能被throw的对象的类型必须是Throwable的子类。
6. 当父类的方法中有声明throws异常类,其子类重写父类的该方法时声明throws时自能使父类所声明的异常类或其子类或者选择不抛出,但不能是其他异常类,否则编译通不过。这点跟方法的返回值类型类似。