一文读懂 Java 异常体系
写程序的时候,编辑器会提示错误,关键字拼错了,语法不符合规则,不符合泛型;程序编译的时候,编译器会提示错误,检查是否符合 Java 的语法规范,没有通过编译器检查的程序就无法编译,也就无法运行。这些都是在程序正式运行之前,先排除掉一些通过 Java 的规范就可以排除调的错误。
Exceptio 和 Error
接着程序才可以正式运行,程序运行时任然会出现异常。针对程序运行时出现的异常,Java 将其分成了两大类,一类是 Exception,一类是 Error,它们都继承自 Throwable 接口。
- Throwable 接口是所有异常(Exception 和 Error)的父类,也只有 Throwable 类型的实例才可以被抛出(throw)和捕获(catch)。具体来说就是继承 Throwable 的类,及其子类,以及 @throw 注解的类。
- Error 是一些不常见的异常,大部分 Error 发生的时会直接导致程序不可用,也就不涉及出现 Error 时该怎么编程处理。比如说 OutOfMemoryError 出现时表明 JVM 中的内存已经满了,我们无法在发生 OutOfMemoryError 时编程处理它,只能以事后分析 GC 日志的方式,对代码、机器或者 JVM 参数进行调整。
- Exception 是程序运行过程中,可以被预料到的,可能会发生的异常。Exception 又分为可检查(checked)异常和不检查(unchecked)异常:
- 可检查异常在源代码里必须显式地进行捕获处理,这是编译期检查的一部分,比如 IOExceptio、SQLException。
- 不检查异常就是所谓的运行时异常,通常是可以编码避免的逻辑错误,具体根据需要来判断是否需要捕获,并不会在编译期强制要求,比如 NullPointerException、ArrayIndexOutOfBoundsException。
- 所以说 UnChecked 异常包括 Error、及 RuntimeException;Checked 异常是 Exception 中处 RuntimeException 之外的异常。
常见的 Exception
RuntimeException
UncheckedException
Java 处理异常的两种手段
Java 处理异常有两种手段:
- 一种是使用 try…catch…finally… 语句块
- 一种是使用 throw 抛出异常
- try…with…resources 是 try…catch…finally… 的设计版,能够帮助我们自动关闭资源
throws、throw
- throw 是在方法中抛出一个异常实例,由该方法的调用者来处理这个异常。
- throws 是在方法上申明该方法可能抛出的异常,告诉调用者调用该方法可能抛出该异常,一般与 throw 成对出现。
try、catch、finally
- 可以是 try…catch 、try…finally、try…catch…finally 的形式
- throws、throw 对异常的处理采用向上层抛出的方式;
- try、catch、finally 则是采用自行在方法中处理异常,当然它的处理方式也可以是继续向上抛出。
try…with…resources
- JDK7 之后增加的语法糖,不需要显示来写关闭资源的方法
异常链
异常链是指我们捕获异常之后,将异常信息传给上层,然后逐层抛出异常,,Java API文档中给出了一个简单模型:
try {
lowLevelOp();
} catch (LowLevelException le) {
throw (HighLevelException) new HighLevelException().initCause(le);
}
当程序捕获到了一个底层异常,在处理部分选择了继续抛出一个更高级别的新异常给此方法的调用者。 这样异常的原因就会逐层传递。这样,位于高层的异常递归调用getCause()方法,就可以遍历各层的异常原因。
自定义异常
自定义异常就是我们自己写一个类,继承某种类型的Exception,在使用它的时候就可以 throw new BusinessException(code, msg);
public class BusinessException extends RuntimeException {
private static final long serialVersionUID = 1L;
private Integer code; //错误码
public BusinessException() {}
public BusinessException(ResultEnum resultEnum) {
super(resultEnum.getMsg());
this.code = resultEnum.getCode();
}
public BusinessException(ResultEnum resultEnum, String errorMsg) {
super(errorMsg);
this.code = resultEnum.getCode();
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
}