《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。

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

相关推荐
_upupup12 分钟前
异常(C++)
java·开发语言·jvm
g105655913916 分钟前
公有云_云运维服务
java·运维·服务器
霸道流氓气质27 分钟前
ComfyUI 图像生成工作流完全指南:从节点编排到Java生产级图像生产实战
java·开发语言·人工智能
再写一行代码就下班38 分钟前
linux sh脚本在windows修改导致无法使用解决方式
java·linux·centos
m0_587383001 小时前
24小时自助健身房软硬件解决方案实战指南:从架构设计到部署实施
java·spring·小程序·架构·需求分析
陆卿之2 小时前
Java对接DeepSeek
java·开发语言·人工智能
庄园特聘拆椅狂魔2 小时前
Java 后端转全栈的第一课:从前端项目搭建到技术选
java·开发语言·前端
烽火聊员2 小时前
Android屏幕卡顿traces.txt拉取查看
android·java·android studio
lzhdim2 小时前
C#不为人知的10个魔法特性:资深开发者也会震惊的底层奥秘
java·前端·javascript·算法·c#
ProcessOn官方账号3 小时前
java IO操作 你快速认识IO的相关基本知识
java·开发语言