標籤:exception java 編程
只針對異常情況才使用異常
異常設計的初衷就是針對程式的不正常情形所使用的,不要使用異常來控製程序的執行流程
對可恢複的情況使用受檢異常,對編程錯誤使用非受檢異常
Java設計了三種可以拋出的結構
- checked exception
- runtim exception
- error
error一般情況下,約定俗稱有虛擬機器使用,表示資源不足等錯誤
對可恢複的情況使用受檢異常,對編程錯誤使用非受檢異常
避免不必要的使用checked exception
使用checked exception會給用戶端程式員帶來很大的負擔,只有滿足如下兩個條件,才應該使用checked exception
- 即使正確調用該api此種情況也可能發生
- 對於異常的發生,程式員可以立即採取有用的動作
否則,應該使用runtime exception
優先使用標準的異常
重用現有的異常,有三個好處
- 使你的api易於學習和使用
- 對於使用api的程式來說,可讀性會更好
- 異常類越少,裝載時的開銷也越小
常用的異常有如下幾個
- IllegalArgumentException
- IllegalStateException
- NullPointerException
- IndexOutOfBoundException
- ConcurrentModificationException
- UnsupportedOperationException
拋出與抽象相對應的異常
當方法要傳遞底層實現拋出的異常時,要進行異常轉譯,不要使底層實現的異常汙染了上層api
例如
catch(IOException e){ throw new ServiceException(e);}
通常有兩種轉譯方式,一種是直接異常的轉譯,一種是異常鏈的轉譯
上面的例子就是異常鏈的轉譯,調用方可以通過異常獲得更底層的異常,方便排查問題,直接轉譯就是不傳遞異常鏈,例如
catch(IOException e){ throw new ServiceException("io exception");}
以上只是針對一定要傳遞底層異常情況下的處理方法,對於底層的方法,首選方案是處理掉底層異常,不將異常的影響傳遞到上層去,一般有兩條途徑來實現
- 對參數進行檢查,避免調用底層方法發現異常
- 繞開異常,將異常記錄下來,不傳播出去
每個方法拋出的異常都要有文檔
為checked exception和unchecked exception都建立文檔說明,但是不要在方法聲明中標記unchecked exception
在細節訊息中包含能捕獲失敗的資訊
要記錄下產生該異常的各種原因,最好能使異常自身記錄下產生問題的原因,例如在異常的建構函式中包含一些特別的欄位,就像在IndexOutOfBoundsException中可以有如下構造方法
public IndexOutOfBoundsException(int lowerBound, int upperBound, int index){ ...
努力使失敗保持原子性
失敗的方法調用應該使對象保持在被調用之前的狀態,有幾種途徑可以實現這個目的
- 使用不可變對象
- 在改變狀態之前檢查參數有效性,提前拋出異常
- 將可能失敗的操作放在改變狀態之前執行,這樣失敗是可以提前結束,不至於使對象處於不一致的狀態
- 寫恢複代碼(不常用),一般是對於已經持久化的資料
- 使操作在一個臨時拷貝上執行
有時,並不總能實現失敗的原子性,例如兩個線程不安全的並發修改對象的狀態
規範上來講,任何調用失敗都應該使對應狀態位於之前的狀態,如何有不一致,應該在文檔中描述出來
不要忽略異常
對於異常,除了關閉InputStream時,其他時候都不要忽略異常
對異常
此建議對於checked 和unchecked異常都使用
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
《Effective Java》——異常