Tips
书中的源代码地址:
注意, 书中的有些代码里方法是基于 Java 9 API 中的, 所以 JDK 最好下载 JDK 9 以上的版本.
72. 赞成使用标准异常
专家级程序员与经验较少的程序员之间的一个区别是, 专家力争并通常实现高度的代码重用. 代码重用是一件好事, 异常也不例外. Java 类库提供了一组异常, 涵盖了大多数 API 的异常抛出需求.
重用标准异常有几个好处. 其中最主要的是, 它使你的 API 更容易学习和使用, 因为它符合程序员已经熟悉的既定约定. 其次, 使用你的 API 的程序更容易阅读, 因为它们不会因为不熟悉的异常而混乱. 最后(也是最不重要的), 更少的异常类意味着更小的内存占用和更少的加载类的时间.
最常用的异常是 IllegalArgumentException(条目 49). 当调用者传入一个不合适的参数值时, 通常抛出这个异常. 例如, 如果调用者在表示某个操作重复次数的参数中传递了一个负数, 则抛出此异常.
另一个常用的异常是 IllegalStateException. 如果由于接收对象的状态而调用是非法的, 则通常会抛出异常. 例如, 如果调用者试图使用尚未正确初始化之前的对象时, 则抛出这个异常.
可以说, 每个错误的方法调用都可以归结为非法参数或状态, 但是还有一些异常通常用于某些类型的非法参数和状态. 如果调用者在禁止 null 值的参数中传递 null, 那么按照惯例, 抛出 NullPointerException, 而不是 IllegalArgumentException 异常. 类似地, 如果调用者将表示索引的参数中的超出范围的值传递给序列, 则应该抛出 IndexOutOfBoundsException, 而不是 IllegalArgumentException.
另一个可重用异常是 ConcurrentModificationException. 如果一个对象被设计为由单个线程使用(或与外部同步), 并且检测到它正在被并发地修改, 则应该抛出该对象. 这个异常最多是一个提示, 因为无法可靠地检测并发修改.
最后一个需要注意的标准异常是 UnsupportedOperationException. 如果对象不支持尝试的操作, 则抛出此异常. 它很少使用, 因为大多数对象都支持它们的所有方法. 此异常用于无法实现由其实现的接口定义的一个或多个 Optional 操作的类. 例如, 如果有人试图从仅支持追加 (append-only ) 的列表中删除元素, 则将抛出此异常.
不要直接重用 Exception,RuntimeException,Throwable 或 Error. 将这些类视为抽象类. 你不能对这些异常进行可靠的测试, 因为它们是方法可能抛出的其他异常的父类.
此表总结了最常见的重用异常:
异常 | 使用场景 |
---|---|
IllegalArgumentException | 不合适的非 null 参数值 |
IllegalStateException | 方法调用状态不适合的对象 |
NullPointerException | 再禁止使用 null 的情况下参数值为 null |
IndexOutOfBoundsException | 索引参数值越界 |
ConcurrentModificationException | 在禁止并发修改对象的地方检测到该对象被并发修改 |
UnsupportedOperationException | 对象不支持方法 |
虽然到目前为止, 这些是最常见的重用异常, 但是在环境允许的情况下也可以重用其他异常. 例如, 如果正在实现诸如复数或有理数之类的算术对象, 那么重用 ArithmeticException 和 NumberFormatException 是合适的. 如果一个异常符合你的需要, 那么继续使用它, 但前提是抛出它的条件与异常文档描述一致: 重用必须基于文档化的语义, 而不仅仅是基于名称. 另外, 如果想添加更多的细节, 可以随意子类化标准异常(条目 75), 但是请记住异常是可序列化的(第 12 章). 这本身就是, 如果没有充分理由, 不要编写自己的异常类的原因.
选择重用哪个异常可能比较棘手, 因为上面表格中的 "使用场景" 似乎并不相互排斥. 考虑表示一副纸牌的对象的情况, 假设有表示发一手牌的方法, 该方法参数是一手牌的纸牌数量. 如果调用者传递的值大于整副牌中剩余的牌的数量, 则可以将其解释为 IllegalArgumentException (handSize 参数值过大), 或者是 IllegalStateException(纸牌中包含的牌太少). 在这种情况下, 规则是, 如果没有参数值, 则抛出 IllegalArgumentException, 否则抛出 IllegalArgumentException 异常.
来源: https://www.cnblogs.com/IcanFixIt/p/10621893.html