第七十三條:拋出與抽象對應(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)譯,如下代碼所示:

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

下面的異常轉(zhuǎn)譯例子取自于AbstractSequentialList類型大刊,該類是List接口的一個骨架實現(xiàn)为迈,詳見第20條。在這個例子中,按照List<E>接口中的get方法的規(guī)范要求葫辐,異常轉(zhuǎn)譯是必需的:

/**
 * Returns the element at the specified position in this list.
 * @throws IndexOutOfBoundsException if the index is out of range
 * ({@code index < 0 || index >= size()}). 
*/
public E get(int index) {
    ListIterator<E> i = listIterator(index); 
    try {
        return i.next();
    } catch (NoSuchElementException e) {
        throw new IndexOutOfBoundsException("Index: " + index); 
    }
}

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

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

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

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

大多數(shù)標(biāo)準的異常都有支持鏈的構(gòu)造器狈涮。對于沒有支持鏈的異常,可以利用Throwable的initCause方法設(shè)置原因鸭栖。異常鏈不僅讓你可以通過程序(用getCause)訪問原因歌馍,還可以將原因的堆棧軌跡繼承到更高層的異常中。

盡管異常轉(zhuǎn)譯與不加選擇地從底層傳遞異常地做法相比有所改進晕鹊,但是也不能濫用它松却。如有可能,處理來自低層異常地最好做法是溅话,在調(diào)用低層方法之前確保它們會成功執(zhí)行玻褪,從而避免它們拋出異常。有時候公荧,可以在給低層傳遞參數(shù)之前,檢查更高層方法參數(shù)地有效性同规,從而避免低層方法拋出異常循狰。

如果無法阻止來自低層的異常,其次的做法是券勺,讓更高層來悄悄地處理這個異常绪钥,從而將高層方法的調(diào)用者與低層地問題隔離開來。在這種情況下关炼,可以用某種適當(dāng)?shù)挠涗洐C制(如java.util.logging)將異常記錄下來程腹。這有助于管理員調(diào)查問題,同時又將客戶端代碼和最終用戶與問題隔離開來儒拂。

總而言之寸潦,如果不阻止或者處理來自更低層的異常,一般的做法是使用異常轉(zhuǎn)譯社痛,只有在低層方法的規(guī)范碰巧可以保證它所拋出的所有異常對于更高層也是合適的情況下见转,才可以將異常從低層傳播到高層。異常鏈對高層和低層異常都提供了最佳的功能:它允許拋出適當(dāng)?shù)母邔赢惓K獍В瑫r又能捕獲低層的原因進行失敗分析(詳見第75條)斩箫。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子乘客,更是在濱河造成了極大的恐慌狐血,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件易核,死亡現(xiàn)場離奇詭異匈织,居然都是意外死亡,警方通過查閱死者的電腦和手機耸成,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門报亩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人井氢,你說我怎么就攤上這事弦追。” “怎么了花竞?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵劲件,是天一觀的道長。 經(jīng)常有香客問我约急,道長零远,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任厌蔽,我火速辦了婚禮牵辣,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘奴饮。我一直安慰自己纬向,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布戴卜。 她就那樣靜靜地躺著逾条,像睡著了一般。 火紅的嫁衣襯著肌膚如雪投剥。 梳的紋絲不亂的頭發(fā)上师脂,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音江锨,去河邊找鬼吃警。 笑死,一個胖子當(dāng)著我的面吹牛啄育,可吹牛的內(nèi)容都是我干的汤徽。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼灸撰,長吁一口氣:“原來是場噩夢啊……” “哼谒府!你這毒婦竟也來了拼坎?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤完疫,失蹤者是張志新(化名)和其女友劉穎泰鸡,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體壳鹤,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡盛龄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了芳誓。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片余舶。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖锹淌,靈堂內(nèi)的尸體忽然破棺而出匿值,到底是詐尸還是另有隱情,我是刑警寧澤赂摆,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布挟憔,位于F島的核電站,受9級特大地震影響烟号,放射性物質(zhì)發(fā)生泄漏绊谭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一汪拥、第九天 我趴在偏房一處隱蔽的房頂上張望达传。 院中可真熱鬧,春花似錦迫筑、人聲如沸宪赶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至罕伯,卻和暖如春曲伊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背追他。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工坟募, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人邑狸。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓懈糯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親单雾。 傳聞我的和親對象是個殘疾皇子赚哗,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容