第61條 拋出與抽象相對應(yīng)的異常

如果方法拋出的異常與它所執(zhí)行的任務(wù)沒有明顯的聯(lián)系,這種情形物會使人不知所措。當(dāng)方法傳遞由低層抽象拋出的異常時,往往會發(fā)生這種情況。除了使人感到困惑之外,這也讓實現(xiàn)細節(jié)污染了更高層的API。如果高層的實現(xiàn)在后續(xù)的發(fā)行版本中發(fā)生了變化,它所拋出的異常也可能會跟著發(fā)生變化,從而潛在地破壞現(xiàn)有的客戶端程序。
  為了避免這個問題,更高層的實現(xiàn)應(yīng)該捕獲低層的異常,同時拋出可以按照高層抽象進行解釋的異常。這種做法被稱為異常轉(zhuǎn)譯(exceptiontranslation),如下所示:

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

下面的異常轉(zhuǎn)譯例子取自于AbstractSequentialList類,該類是List接口的一個骨架實現(xiàn)(skeletal implementation)(見第18條)。在這個例子中,按照List<E>接口中g(shù)et方法的規(guī)范要求,異常轉(zhuǎn)譯是必需的:

/**
     * 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);
        }
    }

一種特殊的異常轉(zhuǎn)譯形式稱為異常鏈(exceptionchaining),如果低層的異常對于調(diào)試導(dǎo)致髙層異常的問題非常有幫助,使用異常鏈就很合適。低層的異常(原因)被傳到髙層的異常,髙層的異常提供訪問方法(Thmwable.getCause)來獲得低層的異常:

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

髙層異常的構(gòu)造器將原因傳到支持鏈(chaining-aware)的超級構(gòu)造器,因此它最終將被傳給Throwable的其中一個運行異常鏈的構(gòu)造器,例如Throwable(Throwable):

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

大多數(shù)標準的異常都有支持鏈的構(gòu)造器。對于沒有支持鏈的異常,可以利用Thmwable的initCause方法設(shè)置原因。異常鏈不僅讓你可以通過程序(用getCause)訪問原因,它還可以將原因的堆棧軌跡集成到更髙層的異常中。
  盡管異常轉(zhuǎn)譯與不加選擇地從低層傳遞異常的做法相比有所改進,但是它也不能被濫用。如有可能,處理來自低層異常的最好做法是,在調(diào)用低層方法之前確保它們會成功執(zhí)行,從而避免它們拋出異常。有時候,可以在給低層傳遞參數(shù)之前,檢査更高層方法的參數(shù)的有效性,從而避免低層方法拋出異常。
  如果無法避免低層異常,次選方案是,讓更髙層來悄悄地繞開這些異常,從而將高層方法的調(diào)用者與低層的問題隔離開來。在這種情況下,可以用某種適當(dāng)?shù)挠涗洐C制(如java.util.logging)將異常記錄下來。這樣有助于管理員調(diào)査問題,同時又將客戶端代碼和最終用戶與問題隔離開來。
  總而言之,如果不能阻止或者處理來自更低層的異常,一般的做法是使用異常轉(zhuǎn)譯,除非低層方法碰巧可以保證它拋出的所有異常對髙層也合適才可以將異常從低層傳播到高居。異常鏈對髙層和低層異常都提供了最佳的功能:它允許拋出適當(dāng)?shù)捏{層異常,同時又能捕獲底層的原因進行失敗分析(見第63條)。

附:異常轉(zhuǎn)譯和異常鏈資料:http://blog.csdn.net/dichyzhu/article/details/3871635

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 通俗編程——白話JAVA異常機制 - 代碼之道,編程之法 - 博客頻道 - CSDN.NEThttp://blog...
    葡萄喃喃囈語閱讀 3,333評論 0 25
  • 第五十七條、只針對異常的情況才使用異常 不要優(yōu)先使用基于異常的模式:因為異常機制的設(shè)計初衷是用于不正常的情況,所以...
    Timorous閱讀 731評論 0 1
  • 1、什么是異常 結(jié)構(gòu)不佳的代碼不能運行,這是Java的基本理念。 發(fā)現(xiàn)錯誤的理想時機是在編譯期。然而,編譯器并不能...
    java部落閱讀 5,053評論 1 4
  • 57、只針對異常的情況才使用異常 在這段代碼中,當(dāng)循環(huán)企圖訪問數(shù)組邊界之外的元素時,拋出異常,以達到終止無限循環(huán)的...
    Alent閱讀 371評論 0 3
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,176評論 25 708

友情鏈接更多精彩內(nèi)容