Java异常处理
Java语言提供了相对完善的异常处理机制,异常体系如下,
- Throwable为异常体系顶层接口,所有异常均继承自该类
- Throwable分为Error和Exception
Error和Exception有何区别?
- Error:是指在正常情况下,不大可能出现的情况,绝大部分的Error都会导致程序(比如JVM自身)处于非正常的、不可恢复状态。此情况下无需捕获处理
- Exception:是程序正常运行中,可以预料的意外情况,可能并且应该被捕获,进行相应处理
Exception 分类
- checked Exception : 源码中必须捕获的异常,编译期检查的一部分
- unchecked Exception : 运行时异常,具体根据需要来判断是否需要捕获,编译期不强制要求是否捕获
Throwable继承体系
RuntimeException
- NullPointerException
- ArrayIndexOutOfBoundException
- ConcurrentModificationException
- UnSupportedOperationException
- ClassCastException
- SecurityException
- …
Checked Exception
- IOException
- InterruptedException
- ClassNotFoundException
- …
捕获、抛出异常
- try-catch-finanlly 块捕获异常,finally进行资源回收
- throw、throws 关键字抛出异常,throw用于方法体内,throws作用于方法上
try-with-resources 和 multiple catch用于优化try-catch-finally块
try-with-resources 要求对象扩展了AutoCloseable 或者 Closeable
异常处理的两个基本原则
- 抛出特定异常,而不是通用异常
- 特定异常使得代码一目了然,方便他人维护
- 避免捕获到不希望捕获的异常
- 不要生吞(swallow)异常
- “吃掉”异常会导致排查问题非常困难
- 不要将异常输出到STERR,这样很难判断异常究竟输出到哪里了
从性能角度探究异常
- try-catch代码段会产生额外的性能开销,尽量不要一个大的try包住整段的代码;不要利用异常替代条件语句(if/else、switch)控制代码流程,这样很低效
- Java每实例化一个Exception,都会对当时的栈进行快照,这是一个相对比较重的操作。如果发生的非常频繁,这个开销可就不能被忽略了。