73. 抛出与抽象对应的异常

      为了避免这个问题, 更高层的实现应该捕获低层的异常,同时抛出可以按照高层抽象进行解释的异常。这种做法称为异常转译 (exception translation),如下代码所示:

      下面的异常转译例子取自于 类,该类是 List 接口的一个骨架实现(skeletal implementation),详见第 20 条。在这个例子中,按照List<E>接口中 get 方法的规范要求,异常转译是必需的:

      高层异常的构造器将原因传到支持链(chaining-aware)的超级构造器,因此它最终将被传给 Throwable 的其中一个运行异常链的构造器,例如 Throwable(Throwable) :

      大多数标准的异常都有支持链的构造器。对于没有支持链的异常,可以利用 Throwable 的 initCause 方法设置原因。异常链不仅让你可以通过程序(用 getCause)访问原因,还可以将原因的堆战轨迹集成到更高层的异常中。

      如果无法阻止来自低层的异常,其次的做法是,让更高层来悄悄地处理这些异常,从而将高层方法的调用者与低层的问题隔离开来。在这种情况下,可以用某种适当的记录机制(如 java.util.logging)将异常记录下来。这样有助于管理员调查问题,同时又将客户端代码和最终用户与问题隔离开来。

      总而言之,如果不能阻止或者处理来自更低层的异常,一般的做法是使用异常转译,只有在低层方法的规范碰巧可以保证“它所抛出的所有异常对于更高层也是合适的”情况下,才可以将异常从低层传播到高层。异常链对高层和低层异常都提供了最佳的功能:它允许抛出适当的高层异常,同时又能捕获低层的原因进行失败分析(详见第 75 条) 。