Java异常了解
异常的层次结构
基本异常
异常情形:指阻止当前方法或作用域继续执行的异常
抛出异常后的动作:
- 使用new在堆上创建异常对象
- 当前程序执行路径被终止,并从当前环境中弹出对异常对象的引用。
- 异常处理机制接管程序,并在异常处理程序(即catch块)处继续执行
- 异常处理程序将程序从错误状态恢复,让程序要么继续执行,要么换一种方式运行。
所有的标准异常类都有二个构造器。一个默认的;一个接受字符串参数(接受异常信息)如throw new NullPointerException("t=null").
捕获异常
try{ //do something }catch(Exception e){ }finally{ //must do }
异常处理有二种模型:
- 终止模型:一旦异常被抛出,则表明错误已无法挽回,也不能回来继续执行。(Java支持终止模型,而且偏向于使用它)
- 恢复模型:修正错误,然后重新尝试调用相同的方法,并认为第二次能成功。
printStackTrace( )方法:打印从方法调用处到异常抛出处的方法调用序列。e.printStackTrace( )将信息输出到标准错误流; e.printStackTrace(System.out),将信息发送到System.out,并自动地被捕获和显示在输出中。
Finally清理异常说明
Java中的finally一般被用于把除内存之外的资源恢复到它的初始状态。因为Java有垃圾回收机制,故无需手动清理内存,但在内存之外的资源则需要在异常抛出程序终止之前被恢复并关闭
- finally可以保证无论异常是否被抛出,其子句总能被执行。
- 当涉及continue和break的时候,finally也会得到执行。配合可代替goto语句
- finally语句也可以在return语句之后执行。
- 如果finally语句中使用了return或者抛出了其他异常,会造成之前的异常丢失
- 若finally中有return语句返回一个值,在try或catch中也存在return语句返回这个值,那么finally里的return会覆盖前面的返回值
异常说明
受检查的异常:在编译时被强制检查的异常。
不受检查的异常:即程序运行时的异常。将被自动被捕获,这些异常来自RunTimeException。自定义异常类必须继承已有的异常类
栈轨迹
- 使用printStackTrace()方法可以打印Throwable和Throwable的调用栈轨迹,会显示此处到异常抛出点的方法调用序列
- 重新抛出异常:在异常处理程序中使用throw关键字可以重新抛出异常。
- printStackTrace()只能显示最开始的异常抛出点的方法调用路径,不能判断重新抛出点。fillInStackTrace()则以重新抛出点为起点更新栈轨迹信息。
Java标准异常
Java运行时会自动检测一些异常,发现并抛出,不必程序员自己主动抛出,所抛出的异常就是Java标准异常。
Java标准异常一般继承自RuntimeException类,即运行时的异常,也被称为不受检查的异常。 RuntimeException没有被捕获时,会直达main方法,并且在程序退出前自动调用printStackTrace()异常的限制
- 当覆盖方法时,只能抛出在基类方法的异常说明里列出的异常
- 当一个类继承的基类和实现的接口中有相同的方法但是抛出不同的异常时,此时应该按照基类来抛出异常
- 异常限制对构造器不起作用,子类构造器可以抛出任何异常而不必理会基类构造器抛出的异常
- 子类构造器不能捕获基类构造器抛出的异常
- 基类抛出异常时,子类可以不抛出异常
构造器的异常处理
在构造阶段可能抛出的异常,并且要求清理的类,最安全的方式是使用嵌套的try子句
在创建对象后,立即进入一个try-finally语句块,这样若创建成功,会在下面的finally语句中进行清理,如创建不成功则跳出上一层try,不进行清理工作异常匹配
- 抛出异常时,异常处理系统会给出最近的处理程序,匹配到最近的处理程序后,则认为异常被处理,则不再继续查找。(所以有多个catch语句时,Exception异常一般在catch语句的最下层)
- catch子句可以捕获参数中声明的异常和它的所有派生异常,若之后还有catch到其派生类异常处理子句,则不会被执行