Guava使用之Throwables異常簡化、錯誤傳播和檢查

任何人都不敢說自己的代碼沒有bug,所以程序拋異常是再經常不過的事情,有時候,你會想把捕獲的exception拋到上一個try/catch塊。對於 RuntimeException 和 Error 尤爲如此,它們不需要try/catch 塊,但可能被其他的 try/catch 塊無意捕獲。

你沒想捕獲它們,但是聲明捕獲Throwable和Exception的時候,也包括了了Error或RuntimeException

Guava提供了若干方法,來判斷異常類型並且重新傳播異常。例如:

try {
    someMethodThatCouldThrowAnything();
} catch (IKnowWhatToDoWithThisException e) {
   handle(e);
} catch (Throwable t) {
   Throwables.propagateIfInstanceOf(t, IOException.class);
   Throwables.propagateIfInstanceOf(t, SQLException.class);
   throw Throwables.propagate(t);
}

所有這些方法都會自己決定是否要拋出異常,但也能直接拋出方法返回的結果例如:throw Throwables.propagate(t); 這樣可以向編譯器聲明這裏一定會拋出異常

Guava中的異常傳播方法簡要列舉如下:

方法 說明
RuntimeException propagate(Throwable) 如果Throwable是Error或RuntimeException,直接拋出;否則把Throwable包裝成RuntimeException拋出。返回類型是RuntimeException,所以你可以像上面說的那樣寫成throw Throwables.propagate(t),Java編譯器會意識到這行代碼保證拋出異常。
void propagateIfInstanceOf( Throwable, Class) throws X Throwable類型爲X才拋出
void propagateIfPossible( Throwable) Throwable類型爲Error或RuntimeException才拋出
void propagateIfPossible( Throwable, Class) throws X Throwable類型爲X, Error或RuntimeException才拋出

下面主要說明一下Throwables.propagate的用法
通常來說,如果調用者想讓異常傳播到棧頂,他不需要寫任何catch代碼塊。因爲他不打算從異常中恢復,他可能就不應該記錄異常,或者有其他的動作。他可能是想做一些清理工作,但通常來說,無論操作是否成功,清理工作都要進行,所以清理工作可能會放在finallly代碼塊中。但有時候,捕獲異常然後再拋出也是有用的:也許調用者想要在異常傳播之前統計失敗的次數,或者有條件地傳播異常。

當只對一種異常進行捕獲和再拋出時,代碼可能還是簡單明瞭的。但當多種異常需要處理時,卻可能變得一團糟:

@Override
public void run() {
try {
        delegate.run();
    } catch (RuntimeException e) {
        failures.increment();
        throw e;
    }catch (Error e) {
        failures.increment();
        throw e;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章