目录
Rule69 只针对异常的情况才使用异常
Rule70 对可恢复的情况使用受检异常,对编程错误使用运行时异常
Rule71 避免不必要的使用受检异常
Rule72 优先使用标准异常
Rule73 抛出与抽象对应的异常
Rule74 每个方法抛出的所有异常都要建立文档
Rule75 在细节消息中包含失败 - 捕获信息
Rule76 努力使失败保持原子性
Rule77 不要忽略异常
看了这篇之后,总结起来就一句话就可以概括了:不要把异常用于正常的控制流中,异常的初衷只是用于不正常的情形。
所有的异常全部继承于Throwable,然后主要分三类
如果需要自定义异常,期望调用者能够适当地恢复,对于这种情况就应该用受检异常。编程错误用运行时异常。一般Error及其子类,不需要我们去新定义,也不建议这样做。
什么叫适当地恢复,我的理解是基础的就像那种重试机制一样,并不是程序错误,有可能是其他原因,例如网络、内存资源不足等等。但是问题是能否恢复的界定并不是那么清晰,如果开发者觉得有一种情况可能允许恢复,建议用受检异常;否则应该用运行时异常。如果不确定能否恢复、建议用运行异常。
上一条中提到,如果不确定能否恢复建议用受检异常。但是受检异常过多也是一种负担,因为不管是catch住之后自行处理,还是直接throw都需要调用方的开发者显示的去处理。而且如果是在Java8的环境下,Stream中无法使用抛出受检异常的方法。
把自己当做是调用方,思考下如果自己调用时遇到了这个受检异常发生。自己能做些什么处理,如果只能catch之后出日志,然后中断程序;或者直接往上一级throw该异常,那么可能这个异常就不太适合用受检异常了。
与之前讲过的优先使用标准函数方法的内容一样,没什么好多说的。
简单来形容的话就是,不同的层次负责处理各自层级的异常。可以通过设置cause形成异常链。
try { ... } catch (LowerLevelException cause) { throw new HighLevelException(cause); }
这个也没啥好说的,文档的重要性之前篇幅里面不少内容都提到过。
往往再出现异常,并希望能够根据异常信息分析问题原因时,最不喜欢看到的就是只打印的异常的名字。因为往往不容易分析原因,最好在异常的细节信息里面包含,必要的参数和域的值,以帮助我们可以定位问题原因或者再现问题。
但是需要注意的是,请不要直接打印客户的密码、密钥、卡号这种敏感信息。日志中的脱敏还是必要的。
因为有些异常,我们希望通过重试机制也好,其他的手段也好进行恢复。如果这个时候,程序运行到一半,抛出了异常,但是改变了原先存储的数据、状态等。那么这个时候等于数据源头被污染了。就像我们提交数据库会使用事务一样的原理。
常见的三种方法保持失败原子性:
请不要catch异常之后,然后什么也不处理也不做,既不往上跑出,也不打印日志等。这样就等于将异常改成了正常的程序流程。关键事后也不好发现分析。
本文技术菜鸟个人学习使用,如有不正欢迎指出修正。xuweijsnj