编程难免会遇到
是程序就少不了异常。异常的正确处理是保证程序健壮性的关键。
异常的分类
- 所有异常源自共同的祖先Throwable
- 异常分为两大类Error和Exception
- Error比较严重,一般是没救了
- Exception可以捕获进行处理,try catch块针对的是这类异常
- Exception中有一类编译器不检查的RuntimeException,一般情况是不该捕获的,应当修正逻辑去避免
JDK中常见的异常,如果没有特殊需求,优先使用自带的异常类
异常原则
- 提早抛出:检测出异常行为立刻抛出,避免继续执行无用的逻辑,也有利于精确定位
- 延迟捕获:当前层面无法处理就不要捕获,交给上级处理
- 检查规避:主动提前检查优于被动捕捉运行时异常,除非无法检查,比如NumberFormatException
异常的负担
如果函数声明了会抛出可被检查的异常,那么所有调用此函数的地方都必须用try-catch捕获
可能的话尽量搭配提前检查的方法避免异常抛出,API设计中最好不要声明可检查异常
1 | try { |
底层函数可能会抛出多种异常,都返给上层的话不光暴露了底层细节,而且也会让上层混乱
应该对异常进行抽象,上层只处理一种类型的异常
1 | try { |
如果构造函数声明了可检查异常,而且作为内部变量直接初始化赋值,那么外部构造函数也必须抛异常
1 | class Sample { |
异常捕获注意点
- 不要在循环中进行
try-catch
,降低执行效率 - 即使try中进行
return
,finally也会执行,但是不会对返回值造成影响
1 | // return foo |
- finally中不应该有
return
,这造成finally块没有正常执行,如果有会覆盖try中结果
1 | // return bar |
Java7
语法支持捕获多个异常。
遇到抛出多种异常的代码,要写很多catch块。如果处理逻辑一样,会造成代码重复。
1 | try{ |
偷懒直接捕获根异常Exception不仅丧失了清晰性,并且连运行时异常也包括,变得不可控。可以使用新语法同时捕获多种类型,进行统一处理
1 | try{ |
exit
退出时不会执行finally
JVM字节码层面不存在finally特殊机制只是一段普通代码,编译时会把finally块复制插入所有执行路径中
如果有System.exit(0)
,那说明已经中断了程序字节码执行,执行不到finally逻辑
如果在退出情况下还想执行逻辑,应该使用Runtime.getRuntime().addShutdownHook()
一分也是爱~
版权声明
This site by Linest is licensed under a Creative Commons BY-NC-ND 4.0 International License.
由Linest创作并维护的博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证。