Java(六) 异常
Java 中的异常处理
在Java 中 通过 Throwable 及其子类描述各种不同的异常类型

Throwable 有两个重要的子类: Exception 和 Error。
Error:这些错误是不可查的,因为他们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况;对于设计合理的程序,即使发生了错误,本质上也不应该试图去处理它所引起的异常状况,因此我们编写程序时不需要关心这类异常。
Exception:是程序本身可以处理的异常,异常处理通常是针对这种类型异常的处理;
Exception类包含 checked exception 和 unchecked exception;
checked exception: Java 编译器会检查这些异常,当程序中可能出现这类异常,要求必须进行异常处理,否则编译不会通过;
unchecked exception:Java 编译器不会检查这些异常,在程序中可以选择捕获处理,也可以不处理,照样能通过编译。
异常处理
在 Java 中,异常处理机制为: 抛出异常、捕获异常;
抛出异常
当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统;
异常对象包含了异常类型 和 异常出现的程序状态等信息;
运行时系统负责寻找处置异常的代码并执行。
捕获异常
在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器;
运行时系统从发生异常的方法开始,依次回查调用栈中的方法,当异常处理器所能处理的异常类型 与 方法抛出的异常类型相符时,即为合适的异常处理器;
当运行时系统遍历调用栈而未找到合适的异常处理器,则运行时系统终止,同时,意味着 Java 程序的终止;
对于运行时异常、错误或可查异常,java 技术所要求的异常处理方式有所不同;
总体来说,java 规定: 对于可查异常必须捕获、或者声明抛出。允许忽略不可查的 RuntimeException 和 Error;
简单来说, 异常总是先被抛出,后被捕获的。
实现: 通过 try、catch、finally、throw、throws 关键字 来实现



终止 finally 执行的 唯一情况

throw & throws
可以通过 throws 声明将要抛出何种类型的异常,通过 throw 将产生的异常抛出;
throws
如果一个方法可能会出现异常,但是没有能力处理这种异常,可以在方法声明处用 throws 子句来声明抛出异常;

当方法抛出异常列表中的异常时,方法将不对这些类型及其子类型的异常做处理,而 抛向 调用该方法 的 方法,由 它去处理;
throws 的使用规则
1、如果是不可查异常(unchecked exception),即Error、RuntimeException或它们的子类,那么可以不使用throws关键字来声明要抛出的异常,编译仍能顺利通过,但在运行时会被系统抛出;
2、如果一个方法中可能出现可查异常,要么用 try-catch 语句捕获,要么用 throws 子句声明将它抛出,否则会导致编译错误;
3、当抛出了异常,则该方法的调用者 必须处理或者重新抛出该异常;
4、当子类重写父类抛出异常的方法时,声明的异常必须是父类方法所声明异常的同类或子类。
throw


比如 throw new IOException();
自定义异常
使用 Java 内置的异常类可以描述在编程时出现的大部分异常情况;
也可以通过自定义异常描述特定业务产生的异常类型;
自定义异常,就是定义一个类,去继承 Throwable 类或者 它的子类



异常链
有时候我们会捕获一个异常后再抛出另一个异常;
异常链就是:将异常发生的原因一个传一个串起来,即把底层的异常信息传给上层,这样逐层抛出.
需要将 底层的异常信息 逐层的往上抛,不然 会造成丢失;
new Exception("我是新产生的异常1", e); // e 就是本层的 错误信息
另一种形式
Exception e1=new Exception("我是新产生的异常2");
e1.initCause(e);
throw e1;
