异常处理机制主要回答了三个问题
- What:异常类型回答了什么被抛出
- Where:异常堆栈跟踪回答了在哪抛出
- Why:异常信息回答了为什么被抛出
Throwable:所有的异常类型的根类
Error:程序本身无法处理的错误这些错误是不可查的,并且它们在应用程序的控制和处理能力之外。编译器不做检查。
Exception:程序本身可以处理的异常,捕获后可能恢复
总结:前者是程序无法处理的错误,后者是可以处理的异常。
分为 运行时异常(派生于 RuntimeException 的异常) 和 其他异常 。
划分这两种异常的规则是:由程序错误(一般是逻辑错误,如错误的类型转换、数组越界等,应该避免)导致的异常属于RuntimeException;
而程序本身没有问题,但由于诸如I/O这类错误(eg:试图打开一个不存在的文件)导致的异常就属于其他异常。
RuntimeException:不可预知的,程序应当自行避免。
非RuntimeException:可预知的,从编译器校验的异常。
从责任角度看
1、Error属于JVM需要负担的责任;
2、RuntimeException 是程序应该负担的责任;
3、Checked Exception 可检查异常时Java编译器应该负担的责任;
- 抛出异常:创建异常对象,交由运行时系统处理
- 捕获异常:寻找合适的异常处理器处理异常,否则终止运行
常见Error 以及 Exception
RuntimeException
- NullPointerException - 空指针引用异常
- ClassCastException - 类型强制转换异常
- IllegalArgumentException - 传递非法参数异常
- IndexOutOfBoundsException - 下标越界异常
- NumberFormatException - 数字格式异常
非RuntimeException
- ClassNotFoundException - 找不到指定class的异常
- IOException - IO操作异常
Error
- NoClassDefFoundError - 找不到class定义的异常
- StackOverflowError - 深递归导致栈被耗尽而抛出的异常
- OutOfMemoryError - 内存溢出异常
Java异常的处理原则
- 具体明确:抛出的异常应能通过异常类名和message准确说明异常的类型和产生异常的原因;
- 提早抛出:应尽可能早的发现并抛出异常,便于精确定位问题;
- 延迟捕获:异常的捕获和处理应尽可能延迟,让掌握更多信息的作用域来处理异常;
主流的异常处理框架
- 设计一个通用的继承自RuntimeException的异常来统一处理
- 其余异常都统一转译为上述异常 AppException
- 在catch之后,抛出上述异常的子类,并提供足以定位的信息
- 由前端接收AppException做统一处理
try-catch的性能
- try-catch 块影响JVM的优化
- 异常对象实例需要保存栈快照等信息,开销较大
网友评论