天天看点

Effective Java(61~65)

第61条 抛出与抽象相对应的异常

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

第62条 每个方法抛出的异常都要有文档

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

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

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

第63条 在细节消息中包含能捕获失败的信息

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

public class IndexOutOfBoundsException {
    public IndexOutOfBoundsException(int lowerBound, int upperBound, int index) {
        super("Lower bound:" + lowerBound + 
            ",Upper bound:" + upperBound + 
            ",Index:" + index);
        this.lowerBound = lowerBound;
        this.upperBound = upperBound;
        this.index = index;
    }
}
           

第64条 努力使失败保持原子性

实现的几种途径:

  • 最简单的方法:设计一个不可变的对象。(失败原子性是必然的)
  • 对于可变对象执行操作的方法,在执行操作之前检查参数的有效性,这可以使在对象的状态被修改之前先抛出适当的异常。
  • 一般的方法:调整计算处理过程的顺序,使得任何有可能失败的计算部分都在对象状态被修改之前发生。
  • 编写一段恢复代码,由它来拦截操作过程中发生的失败,以及使对象回滚到操作开始之前的状态上。(主要用于永久性的(基于磁盘的)数据结构)
  • 在对象的一份临时拷贝上执行操作,当操作完成后再用临时拷贝的结果代替对象的内容。例如:

    Collections.sort

    在执行排序之前,首先把它的输入列表转入到一个数组中,以便降低在排序的内循环中访问元素所需要的开销。

第65条 不要忽略异常 

  • 当API的设计者声明一个方法将要抛出某个异常时,他们等于在试图说明某些事情,所以不要用一个空的catch块来忽略它。会使异常得不到应有的目的。
  • 有一条情况可以忽略:即关闭FileInputStream的时候,因为还没有改变文件的状态,因此不必执行任何恢复动作,并且文件中读取到所需要的信息,因此不必终止正在进行的操作,但是此时把异常记录下来是一个明智的做法,可以因此调查异常的原因。

继续阅读