美文网首页Effective Java
第61条 抛出与抽象相对应的异常

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

作者: 呼天阔 | 来源:发表于2017-09-05 13:13 被阅读0次

如果方法抛出的异常与它所执行的任务没有明显的联系,这种情形物会使人不知所措。当方法传递由低层抽象抛出的异常时,往往会发生这种情况。除了使人感到困惑之外,这也让实现细节污染了更高层的API。如果高层的实现在后续的发行版本中发生了变化,它所抛出的异常也可能会跟着发生变化,从而潜在地破坏现有的客户端程序。
  为了避免这个问题,更高层的实现应该捕获低层的异常,同时抛出可以按照高层抽象进行解释的异常。这种做法被称为异常转译(exceptiontranslation),如下所示:

        try{
            //Use lower-level abstraction to do our bidding
            ...
        }cache(LowerLevelException e){
            throw new HigherLevelException(...);
        }

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

/**
     * Returns the element at the specified position in this list.
     *
     * <p>This implementation first gets a list iterator pointing to the
     * indexed element (with <tt>listIterator(index)</tt>).  Then, it gets
     * the element using <tt>ListIterator.next</tt> and returns it.
     *
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E get(int index) {
        try {
            return listIterator(index).next();
        } catch (NoSuchElementException exc) {
            throw new IndexOutOfBoundsException("Index: "+index);
        }
    }

一种特殊的异常转译形式称为异常链(exceptionchaining),如果低层的异常对于调试导致髙层异常的问题非常有帮助,使用异常链就很合适。低层的异常(原因)被传到髙层的异常,髙层的异常提供访问方法(Thmwable.getCause)来获得低层的异常:

        try{
           ...    //Use lower-level abstraction to do our bidding
        }cache(LowerLevelException cause){
            throw new HigherLevelException(cause);
        }

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

// Exception with chaining-aware constructor
class HigherLevelException extends Exception {
    HigherLevelExceptionCThrowable cause) {
        super(cause);
    }
}

大多数标准的异常都有支持链的构造器。对于没有支持链的异常,可以利用Thmwable的initCause方法设置原因。异常链不仅让你可以通过程序(用getCause)访问原因,它还可以将原因的堆栈轨迹集成到更髙层的异常中。
  尽管异常转译与不加选择地从低层传递异常的做法相比有所改进,但是它也不能被滥用。如有可能,处理来自低层异常的最好做法是,在调用低层方法之前确保它们会成功执行,从而避免它们抛出异常。有时候,可以在给低层传递参数之前,检査更高层方法的参数的有效性,从而避免低层方法抛出异常。
  如果无法避免低层异常,次选方案是,让更髙层来悄悄地绕开这些异常,从而将高层方法的调用者与低层的问题隔离开来。在这种情况下,可以用某种适当的记录机制(如java.util.logging)将异常记录下来。这样有助于管理员调査问题,同时又将客户端代码和最终用户与问题隔离开来。
  总而言之,如果不能阻止或者处理来自更低层的异常,一般的做法是使用异常转译,除非低层方法碰巧可以保证它抛出的所有异常对髙层也合适才可以将异常从低层传播到高居。异常链对髙层和低层异常都提供了最佳的功能:它允许抛出适当的髙层异常,同时又能捕获底层的原因进行失败分析(见第63条)。

附:异常转译和异常链资料:http://blog.csdn.net/dichyzhu/article/details/3871635

相关文章

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

    如果方法抛出的异常与它所执行的任务没有明显的联系,这种情形物会使人不知所措。当方法传递由低层抽象抛出的异常时,往往...

  • 第 73 条:抛出与抽象相对应的异常

  • 第七十三条:抛出与抽象对应的异常

    如果方法抛出的异常与它所执行的任务没有明显的联系,这种情形将会使人不知所措。当方法传递由底层抽象抛出的异常时,往往...

  • try...catch...finally...

    异常捕捉,一定要抛出对应的异常类型,否则外层异常可能捕捉不到比如方法②抛出IOException异常,方法②在方法...

  • 一文读懂 JAVA 异常处理

    JAVA 异常类型结构 Error 和 Exeption 受查异常和非受查异常 异常的抛出与捕获 直接抛出异常 封...

  • 聊一聊 RxJava2 中的异常及处理方式

    众所周知,RxJava2 中当链式调用中抛出异常时,如果没有对应的 Consumer 去处理异常,则这个异常会被抛...

  • 异常抛出

    本章主要内容 用try语句捕获异常 常见异常处理 用raise 和assert抛出异常 自定义异常 常用异常名 总...

  • 抛出异常

    在方法执行的时候,遇到不匹配的地方,加入异常抛出机制,可以清晰的知道异常点,并很好的解决。 throw new E...

  • 抛出异常

  • 抛出异常

    MSSQL 在存储过程中进程会处理一些逻辑性的错误,如:将RMB转换为USD时,没有查询到想要的汇率 这个时候最好...

网友评论

    本文标题:第61条 抛出与抽象相对应的异常

    本文链接:https://www.haomeiwen.com/subject/cceujxtx.html