异常处理理论上由两种模型:1、终止模型:错误非常关键,一旦发生,程序不能在继续执行下去。无法挽回了。
2、恢复模型:异常处理的工作是恢复程序的工作。然后尝试重新调用出错的方法。(不推荐,增加了过多的耦合,不容易维护)
创建自定义异常
必须从已有的异常类继承。
重新抛出异常:
try{
m();
} catch(Exception e){
throw (Exception)e.fillInStackTrace();//m()中的异常发生地将被这边新的异常发生地取代,异常栈轨迹中将不会存在捕获的这个异常的栈轨迹(抛出的是相同异常的条件下)
}
在捕获异常后抛出另一种异常时,捕获的的异常的栈轨迹将会被取代,与fillInStackTrace()效果类似。
异常链:常常会想要在捕获一个异常后抛出另一个异常,并且希望把原始异常的信息保存下来,这被称为异常链。只有三种异常支持异常链(通过构造器的方式):Error、Exception和RuntimeException。其他的异常类通过initCause()方法而不是构造器(在异常的后面插入)。
Java标准异常
Throwable这个Java类被用来表示任何可以作为异常被抛出的类。Throwable对象可以被分为两种类型(指从Throwable继承而得到的类型):Error用来表示编译时和系统错误;Exception是可以被抛出的基本类型,在Java类库、用户方法以及运行时故障中都可能抛出Exception型异常。所以Java程序员关心的基本类型通常时Exception。
使用finally进行清理
通常适用于内存回收之外的情况(因为这些垃圾回收器做了)。finally语句块总是会执行。
缺憾:异常丢失
Java的异常实现也有缺陷,异常作为程序出错的标志,绝不应该被忽略,但它还是有可能被忽略。用某些特殊的方式使用finally
public class Test_ignore_exception { class ExceptionA extends Exception { static final long serialVersionUID = 1L; public String toString(){ return "A is important exception ! "; } } class ExceptionB extends Exception { static final long serialVersionUID = 1L; public String toString(){ return "B is trivial exception ! "; } } void f() throws ExceptionA{ throw new ExceptionA(); } void dispose() throws ExceptionB{ throw new ExceptionB(); } public static void main(String[] args) { try { Test_ignore_exception t = new Test_ignore_exception(); try { t.f(); } finally{ t.dispose(); } } catch (Exception e) { System.out.println(e); } } } 运行结果: B is trivial exception !
我们发现A异常被B异常覆盖了,与异常链有点类似,在catch中抛出新的异常,之前的异常信息的栈信息将会丢失。
异常的限制:子类覆盖父类的方法时,只能抛出父类抛出的类型。范围是父类的子集。简单来说,就是为了实现多态的特性。