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

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

相关推荐
码农水水7 小时前
蚂蚁Java面试被问:混沌工程在分布式系统中的应用
java·linux·开发语言·面试·职场和发展·php
海边的Kurisu7 小时前
苍穹外卖日记 | Day4 套餐模块
java·苍穹外卖
毕设源码-邱学长7 小时前
【开题答辩全过程】以 走失儿童寻找平台为例,包含答辩的问题和答案
java
他们叫我技术总监8 小时前
Python 列表、集合、字典核心区别
android·java·python
江沉晚呤时8 小时前
从零实现 C# 插件系统:轻松扩展应用功能
java·开发语言·microsoft·c#
梁下轻语的秋缘8 小时前
ESP32-WROOM-32E存储全解析:RAM/Flash/SD卡读写与速度对比
java·后端·spring
wanzhong23338 小时前
开发日记8-优化接口使其更规范
java·后端·springboot
Knight_AL8 小时前
Java 多态详解:概念、实现机制与实践应用
java·开发语言
C雨后彩虹8 小时前
volatile 实战应用篇 —— 典型场景
java·多线程·并发·volatile
xie_pin_an8 小时前
从二叉搜索树到哈希表:四种常用数据结构的原理与实现
java·数据结构