《Effective Java》知识点(9)--异常

69. 只针对异常的情况才使用异常

异常应该只用于异常的情况下,永远不应该用于正常的控制流。例如基于异常的循环模式会模糊代码的意图,降低性能,还不能保证能正常工作。

设计良好的API不应该强迫它的客户端为了正常的控制流而使用异常。

方法 原则
返回optional或可识别的返回值(比如null) 1.对象在缺少外部同步的情况下被并发访问,或者可被外部改变状态 2. 重复"状态相关"方法的工作
提供"状态测试"方法(比如hasNext) 其它情形(因为可读性更好,易于检测,抛出异常)
70. 对可恢复的情况使用受检异常,对编程错误使用运行时异常
可抛出结构 原则
受检异常 可恢复,提供辅助方法,以便调用者能适当恢复
运行时异常 编程错误(如前提违例),不确定是否可恢复,抛出未受检异常
错误 不要实现新的Error子类
71. 避免不必要地使用受检异常

在谨慎使用的前提下,受检异常可以提升程序的可读性;但如果过度使用,将会使API使用起来非常痛苦。

消除受检异常的最容易的方法是,返回optional。缺点是无法返回任何额外的信息。

72. 优先使用标准的异常

不要直接重用Exception、RuntimeException、Throwable或者Error。对待这些类要像对待抽象类一样。无法可靠地测试这些异常,因为它们是一个方法可能抛出其它异常的超类。

常见异常 使用场合
IllegalArgumentException 非null的参数值不正确
IllegalStateException 不适合方法调用的对象状态
NullPointerException 在禁止使用null的情况下参数值为null
IndexOutOfBoundsException 下标参数值越界
ConcurrentModificationException 在禁止并发修改的情况下,检测到对象的并发修改
UnsupportOperationException 对象不支持用户请求的方法

异常是可序列化的,如果没有非常正当的理由,千万不要自己编写异常类。

73. 抛出与抽象对应的异常

更高层的实现应该捕获低层的异常,同时抛出可以按照高层抽象进行解释的异常。这种做法称为异常转译。一种特殊的异常转译形式称为异常链。

如果不能阻止或者处理来自更低层的异常,一般的做法是使用异常转译,只有在低层方法的规范碰巧可以保证"它所抛出的所有异常对于更高层也是合适的"情况下,才可以将异常从低层传播到高层。异常链对高层和低层异常都提供了最佳的功能:它允许抛出适当的高层异常,同时又能捕获低层的原因进行失败分析。

74. 每个方法抛出的所有异常都要建立文档

始终要单独地声明受检异常,并且利用Javadoc的@throws标签,准确地记录下抛出每个异常的条件。

使用Javadoc的@throws标签记录下一个方法可能抛出的每个受检异常,但是不要使用throws关键字将未受检的异常包含在方法的声明中。

如果一个类中的许多方法出于同样的原因而抛出同一个异常,在该类的文档注释中对这个异常建立文档,这是可以接受的,而不是为每个方法单独建立文档。

75. 在细节信息中包含失败-捕获信息

为了捕获失败,异常的细节信息应该包含"对该异常有贡献"的所有参数和域的值。

为了确保在异常的细节信息中包含足够的失败-捕捉信息,一种方法是在异常的构造器而不是字符串细节信息中引入这些信息。

为异常的失败-捕获信息提供一些访问方法是合适的。

千万不要在细节信息中包含密码、密钥以及类似的信息。

76. 努力使失败保持原子性

失败的方法调用应该使对象保持在被调用之前的状态。具有这种属性的方法被称为具有失败原子性(failure atomic)。

获得失败原子性的4种方法:

a. 在执行操作之前检查参数的有效性。在对象状态改变前抛出异常。

b. 调整计算处理过程的顺序,使得任何可能会失败的计算部分都在对象状态被修改之前发生。

c. 在对象的一份临时拷贝上执行操作,当操作完成后再用临时拷贝中的结果代替对象的内容。

d. 编写一段恢复代码,由它来拦截操作过程中发生的失败,以及使对象回滚到操作前的状态。

77. 不要忽略异常

空的catch块会使异常达不到应有的目的。

如果选择忽略异常,catch块中应该包含一条注释,说明为什么可以这么做,并且变量应该命名为ignored。

正确地处理异常能够彻底避免失败。只要将异常传播给外界,至少会导致程序迅速失败,从而保留了有助于调试该失败条件的信息。

相关推荐
程序媛-徐师姐几秒前
Java 基于SpringBoot+vue框架的老年医疗保健网站
java·vue.js·spring boot·老年医疗保健·老年 医疗保健
yngsqq1 分钟前
c#使用高版本8.0步骤
java·前端·c#
尘浮生11 分钟前
Java项目实战II基于微信小程序的校运会管理系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
小白不太白95015 分钟前
设计模式之 模板方法模式
java·设计模式·模板方法模式
Tech Synapse17 分钟前
Java根据前端返回的字段名进行查询数据的方法
java·开发语言·后端
xoxo-Rachel24 分钟前
(超级详细!!!)解决“com.mysql.jdbc.Driver is deprecated”警告:详解与优化
java·数据库·mysql
乌啼霜满天24925 分钟前
JDBC编程---Java
java·开发语言·sql
色空大师38 分钟前
23种设计模式
java·开发语言·设计模式
闲人一枚(学习中)39 分钟前
设计模式-创建型-建造者模式
java·设计模式·建造者模式