Java中Exception 和 Error 的区别
文章目录
经典回答:
Exception 和 Error 都是继承了 Throwable 类,在 Java 中只有 Throwable 类型的实例才可以被抛出(throw)或者捕获(catch),它是异常处理机制的基本组成类型。
Exception 和 Error 体现了 Java 平台设计者对不同异常情况的分类。Exception 是程序正常运行中,可以预料的意外情况,可能并且应该被捕获,进行相应处理。
Error 是指在正常情况下,不大可能出现的情况,绝大部分的 Error 都会导致程序(比如 JVM自身)处于非正常的、不可恢复状态。既然是非正常情况,所以不便于也不需要捕获,常见的比如 OutOfMemoryError 之类,都是 Error 的子类。
Exception 又分为检查型(checked)异常和非检查型(unchecked)异常,检查型异常在源代码里必须显式地进行捕获处理,这是编译期检查的一部分。
非检查型异常就是所谓的运行时异常,均继承于RuntimeException,类似 NullPointerException、ArrayIndexOutOfBoundsException 之类,通常是可以编码避免的逻辑错误,具体根据需要来判断是否需要捕获,并不会在编译期强制要求。
Exception 和 Error 举例
备注:
1. NoClassDefFoundError 和 ClassNotFoundException 的区别:
NoClassDefFoundError: 编译成功后,执行程序时Class被删除报此错误
ClassNotFoundException: 动态加载Class如:Class.forName()、ClassLoader.loadClass()时,发现Class不存在,则会抛出此异常。
2. 为什么RuntimeException及其子类是非检查型异常,RuntimeException 不也是继承自Exception吗?
RuntimeException 这类异常在编译器层面进行了特殊处理,参考自 资料2。
关于异常使用过程中需要注意的几点
- 可以使用 try-with-resources 和 multiple catch 减少代码,但是可能实际上编译后的代码更加啰嗦;
- 尽量不要捕获类似Exception这样的通用异常,而应该捕获代码实际上会抛出的异常;
- 不要生吞异常,即捕获异常后,既不输出也不进行处理;
- 由于 e.printStackTrace() 是输出到标准错误流中,在大型系统中,很难判断到底是输出到哪儿去了,所以最好是详细输出到日志系统中;
- Throw early, catch late 原则,尽可能早的抛出异常避免堆栈信息过长,从而无法快速定位问题;catch late 指的是当下捕获异常后难以进行业务或逻辑上的处理,可以将其继续往上抛,在更高层因为业务、逻辑更清晰,会更便于处理;
- 关于 checkedException 和 RuntimeException 的选择
个人理解:checkException 更像是大概率、客观上可能会出现的异常;而RuntimeExceptin则更像是小概率、主观上(例如1/0、数组越界等)可能出现的异常;
官方解释:checkedException 是指异常发生后可以恢复程序,RuntimeException 是指异常发生后,无法恢复; - 关于try catch 对性能的影响,实际上是:可能会抑制JVM对try里面代码的优化,这里的性能影响应该是非常小的;而更有影响的应该是抛出异常时,由于JVM需要保存方法调用的堆栈信息,此处性能更为消耗性能,特别是在抛出异常较多时。
PS:《Java核心技术36讲》第二讲读书笔记
参考资料:
- https://*.com/questions/16451777/is-it-expensive-to-use-try-catch-blocks-even-if-an-exception-is-never-thrown?tdsourcetag=s_pctim_aiomsg
- https://*.com/questions/11547914/why-runtime-exception-is-unchecked-exception