Tips
書中的源代碼地址:https://github.com/jbloch/effective-java-3e-source-code
注意,書中的有些代碼裏方法是基於Java 9 API中的,因此JDK 最好下載 JDK 9以上的版本。java
專家級程序員與經驗較少的程序員之間的一個區別是,專家力爭並一般實現高度的代碼重用。代碼重用是一件好事,異常也不例外。Java類庫提供了一組異常,涵蓋了大多數API的異常拋出需求。git
重用標準異常有幾個好處。其中最主要的是,它使你的API更容易學習和使用,由於它符合程序員已經熟悉的既定約定。其次,使用你的API的程序更容易閱讀,由於它們不會由於不熟悉的異常而混亂。最後(也是最不重要的),更少的異常類意味着更小的內存佔用和更少的加載類的時間。程序員
最經常使用的異常是IllegalArgumentException(條目 49)。 當調用者傳入一個不合適的參數值時,一般拋出這個異常。 例如,若是調用者在表示某個操做重複次數的參數中傳遞了一個負數,則拋出此異常。github
另外一個經常使用的異常是IllegalStateException。 若是因爲接收對象的狀態而調用是非法的,則一般會拋出異常。 例如,若是調用者試圖使用還沒有正確初始化以前的對象時,則拋出這個異常。併發
能夠說,每一個錯誤的方法調用均可以歸結爲非法參數或狀態,可是還有一些異常一般用於某些類型的非法參數和狀態。若是調用者在禁止null值的參數中傳遞null,那麼按照慣例,拋出NullPointerException,而不是IllegalArgumentException異常。相似地,若是調用者將表示索引的參數中的超出範圍的值傳遞給序列,則應該拋出IndexOutOfBoundsException,而不是IllegalArgumentException。app
另外一個可重用異常是ConcurrentModificationException。若是一個對象被設計爲由單個線程使用(或與外部同步),而且檢測到它正在被併發地修改,則應該拋出該對象。這個異常最可能是一個提示,由於沒法可靠地檢測併發修改。學習
最後一個須要注意的標準異常是UnsupportedOperationException。若是對象不支持嘗試的操做,則拋出此異常。它不多使用,由於大多數對象都支持它們的全部方法。此異經常使用於沒法實現由其實現的接口定義的一個或多個Optional操做的類。例如,若是有人試圖從僅支持追加(append-only )的列表中刪除元素,則將拋出此異常。測試
不要直接重用Exception、RuntimeException、Throwable或Error。將這些類視爲抽象類。你不能對這些異常進行可靠的測試,由於它們是方法可能拋出的其餘異常的父類。線程
此表總結了最多見的重用異常:設計
異常 | 使用場景 |
---|---|
IllegalArgumentException | 不合適的非null參數值 |
IllegalStateException | 方法調用狀態不適合的對象 |
NullPointerException | 再禁止使用null的狀況下參數值爲null |
IndexOutOfBoundsException | 索引參數值越界 |
ConcurrentModificationException | 在禁止併發修改對象的地方檢測到該對象被併發修改 |
UnsupportedOperationException | 對象不支持方法 |
雖然到目前爲止,這些是最多見的重用異常,可是在環境容許的狀況下也能夠重用其餘異常。例如,若是正在實現諸如複數或有理數之類的算術對象,那麼重用ArithmeticException和NumberFormatException是合適的。若是一個異常符合你的須要,那麼繼續使用它,但前提是拋出它的條件與異常文檔描述一致:重用必須基於文檔化的語義,而不單單是基於名稱。另外,若是想添加更多的細節,能夠隨意子類化標準異常(條目 75),可是請記住異常是可序列化的(第12章)。這自己就是,若是沒有充分理由,不要編寫本身的異常類的緣由。
選擇重用哪一個異常可能比較棘手,由於上面表格中的「使用場景」彷佛並不相互排斥。考慮表示一副紙牌的對象的狀況,假設有表示發一手牌的方法,該方法參數是一手牌的紙牌數量。若是調用者傳遞的值大於整副牌中剩餘的牌的數量,則能夠將其解釋爲IllegalArgumentException (handSize參數值過大),或者是IllegalStateException(紙牌中包含的牌太少)。在這種狀況下,規則是,若是沒有參數值,則拋出IllegalArgumentException,不然拋出IllegalArgumentException異常。