* 只针对异常的情况才使用异常:异常应该只用于异常的情况下,它永远不应该用于正常的控制流。
如果类具有“状态相关”的方法,即只有在特定的条件下才能被调用的方法,这个类往往也应该有个单独
的状态测试方法。如Iterator的hasNext()和next()。
*********************************************************************
* 对可恢复的情况使用受检异常,对编程错误使用运行时异常:
如果期望调用者能够适当地恢复,对于这种情况应该使用受检异常。通过抛出受检异常,强迫调用者在
try catch子句中处理该异常或者将它传播出去。
如果程序抛出未受检的异常或者错误,往往属于不可回复的情景,如果没有捕捉到这样的异常,将导致
当前线程终止,并出现适当的错误信息。
Error往往被JVM保留用于表示资源不足、约束失败或者其他程序无法继续执行的条件,最好不要再实现
任何新的Error子类。
*********************************************************************
* 优先使用标准的异常:
最经常被重用的异常:非法参数IllegalArgumentException、非法状态IllegalStateException。
不允许null的参数中传递了null使用NullPointerException,表示序列下标的参数中传递了越界的值使用
IndexOutOfBoundsException,不支持或需要被覆盖的操作使用UnsupportedOperationException
*********************************************************************
* 抛出与抽象相对应的异常:
更高层的实现应该捕获底层的异常,同时抛出可以按照高层抽象进行解释的异常。这种行为称为异常转译
(Exception translation)。
*********************************************************************
* 努力使失败保持原子性:
一般而言,失败的方法调用应该使对象保持在被调用之前的状态。具有这种属性的方法称为具有失败
原子性。
* 实现失败原子性的途径:
(1)最简单的办法是设计一个不可变对象。
(2)对于可变对象上执行操作的方法,最常见的做法是,在执行操作之前检查参数的有效性。这可以使
对象被修改之前先抛出适当的异常。
类似的方法是,调整计算处理过程的顺序,使得任何可能会失败的计算部分都在状态被修改之前发生。
(3)第三种做法是编写一段恢复代码由它来拦截操作中发生的失败,以及使对象回滚到操作开始之前的
状态上,通常用于永久性的数据结构(基于磁盘的数据结构)。
(4)第四种做法是在对象的临时拷贝上进行操作,当操作完成之后再用临时拷贝中的结果替换对象的内容。