??????? 專家級程序員與缺乏經(jīng)驗的程序員一個最主要的區(qū)別在于耸峭,專家追求并且通常也能夠?qū)崿F(xiàn)髙度的代碼重用上渴。代碼重用是值得提倡的,這是一條通用的規(guī)則犬钢,異常也不例外。java平臺類庫提供了一組基本的未受檢的異常?思灰,它們滿足了絕大多數(shù)API的異常拋出需要玷犹。本條目中,我們將討論這些常見的可重用異常洒疚。
??????? 重用現(xiàn)在的異常有多方面的好處歹颓。其中最主要的好處是,它使你的API更加容易學(xué)習(xí)和使用油湖,因為它與程序員已經(jīng)熟悉的習(xí)慣用法是一致的.第二個好處是巍扛,對于用到這些API的程序而言,它們的可讀性會更好乏德,因為它們不會出現(xiàn)很多程序員不熟悉的異常电湘。最后(也不是最重要的)一點是,異常類越少鹅经,意味著內(nèi)存印跡(footprint)就越小寂呛,裝載這些類的時間開銷也越少。
? ? ? 最經(jīng)常被重用的異常是IllegalArgumentException瘾晃。當(dāng)調(diào)用者傳遞的參數(shù)值不合適的時候贷痪,往往就會拋出這個異常。例如蹦误,假設(shè)一個參數(shù)代表了“某個動作的重復(fù)次數(shù)”劫拢,如果程序員給這個參數(shù)傳遞了一個負數(shù)肉津,就會拋出這個異常。
??????? 另一個經(jīng)常被重用的異常是IllegalStateExccption舱沧。如果因為接收對象的狀態(tài)而使調(diào)用非法妹沙,通常就會拋出這個異常。例如熟吏,如果在某個對象被正確地初始化之前距糖,調(diào)用者就企圖使用這個對象,就會拋出這個異常牵寺。
? ? ? ? 可以這么說悍引,所有錯誤的方法調(diào)用都可以被歸結(jié)為非法參數(shù)或者非法狀態(tài),但是帽氓,其他還有一些標(biāo)準(zhǔn)異常也被用于某些特定情況下的非法參數(shù)和非法狀態(tài)趣斤。如果調(diào)用者在某個不允許null值的參數(shù)中傳遞了null,習(xí)慣的做法就是拋出NullPointerException,而不是IllegalArgumentException。同樣地黎休,如果調(diào)用者在表示序列下標(biāo)的參數(shù)中傳遞了越界的值浓领,應(yīng)該拋出的就是IndexOutOfBoundsException,而不是IllegalArgumentException
?????? 另一個值得了解的通用異常是ConcurremModificationException。如果一個對象被設(shè)計為專用于單線程或者與外部同步機制配合使用势腮,一旦發(fā)現(xiàn)它正在(或已經(jīng))被并發(fā)地修改镊逝,就應(yīng)該拋出這個異常。
??????? 最后一個值得注意的通用異常是UnsupportedOperationException嫉鲸。如果對象不支持所請求的操作,就會拋出這個異常歹啼。與本條目中討論的其他異常相比玄渗,它很少用到,因為絕大多數(shù)對象都會支持它們實現(xiàn)的所有方法狸眼。如果接口的具體實現(xiàn)沒有實現(xiàn)該接口所定義的一個或者多個可選操作藤树,它就可以使用這個異常。例如拓萌,對于只支持追加操作的List實現(xiàn)岁钓,如果有人試圖從列表中刪除元素,它就會拋出這個異常微王。
以下概括了最常見的可重用異常屡限。
異 常 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 使用場合
IllegalArgumentExccplion 非null的參數(shù)值不正確
lllegalStateException 對于方法調(diào)用而言,對象狀態(tài)不合適
NullPointerExceplion 在禁止使用null的情況下參數(shù)值為null
IndexOutOfBoundsException 下標(biāo)參敗值越界
ConcurrentModificationExcepiion 在禁止并發(fā)修改的情況下炕倘,檢測到對象的并發(fā)修改
UnsupportedOperationExccption 對象不支持用戶請求的方法
??????? 雖然它們是Java平臺類庫中迄今為止最被重用的異常钧大,但是,在條件許可的情況下罩旋,其他的異常也可以被重用啊央。例如眶诈,如果要實現(xiàn)諸如復(fù)數(shù)或者有理數(shù)之類的算術(shù)對象,也可以重用ArithmeticException和NumberFormatException瓜饥。如果某個異常能夠滿足你的需要逝撬,就不要猶像,使用就是乓土,不過宪潮,一定要確保拋出異常的條件與該異常的文檔中描述的條件一致。這種重用必須邊立在語義的基礎(chǔ)上帐我,而不是建立在名稱的基礎(chǔ)之上坎炼。而且,如果希望稍微增加更多的失敗-捕獲(failure-capture)信息(見第63條)拦键,可以放心地把現(xiàn)有的異常進行子類化谣光。
??????? 最后,一定要清楚芬为,選擇重用哪個異常并不總是那么精確萄金,因為上表中的“使用場合”并不是相互排斥的。例如媚朦,考慮表示一副紙牌的對象氧敢。假設(shè)有個處理發(fā)牌操作的方法,它的參數(shù)是發(fā)一手牌的紙牌張數(shù)询张。假設(shè)調(diào)用者在這個參數(shù)中傳遞的值大于整副紙牌的剩余張數(shù)孙乖。這種情形既可以被解釋為IllegalArgurnemException(handSize參數(shù)的值太大),也可以被解釋為IllegalStateException(相對于客戶的請求而言份氧,紙牌對象包含的紙牌太少)唯袄。在這個例子中,感覺IllegalArgumemException要好一些蜗帜,不過恋拷,這里并沒有嚴(yán)格的規(guī)則。