??????? 專家級(jí)程序員與缺乏經(jīng)驗(yàn)的程序員一個(gè)最主要的區(qū)別在于,專家追求并且通常也能夠?qū)崿F(xiàn)髙度的代碼重用。代碼重用是值得提倡的,這是一條通用的規(guī)則,異常也不例外。java平臺(tái)類庫(kù)提供了一組基本的未受檢的異常?,它們滿足了絕大多數(shù)API的異常拋出需要。本條目中,我們將討論這些常見的可重用異常。
??????? 重用現(xiàn)在的異常有多方面的好處。其中最主要的好處是,它使你的API更加容易學(xué)習(xí)和使用,因?yàn)樗c程序員已經(jīng)熟悉的習(xí)慣用法是一致的.第二個(gè)好處是,對(duì)于用到這些API的程序而言,它們的可讀性會(huì)更好,因?yàn)樗鼈儾粫?huì)出現(xiàn)很多程序員不熟悉的異常。最后(也不是最重要的)一點(diǎn)是,異常類越少,意味著內(nèi)存印跡(footprint)就越小,裝載這些類的時(shí)間開銷也越少。
? ? ? 最經(jīng)常被重用的異常是IllegalArgumentException。當(dāng)調(diào)用者傳遞的參數(shù)值不合適的時(shí)候,往往就會(huì)拋出這個(gè)異常。例如,假設(shè)一個(gè)參數(shù)代表了“某個(gè)動(dòng)作的重復(fù)次數(shù)”,如果程序員給這個(gè)參數(shù)傳遞了一個(gè)負(fù)數(shù),就會(huì)拋出這個(gè)異常。
??????? 另一個(gè)經(jīng)常被重用的異常是IllegalStateExccption。如果因?yàn)榻邮諏?duì)象的狀態(tài)而使調(diào)用非法,通常就會(huì)拋出這個(gè)異常。例如,如果在某個(gè)對(duì)象被正確地初始化之前,調(diào)用者就企圖使用這個(gè)對(duì)象,就會(huì)拋出這個(gè)異常。
? ? ? ? 可以這么說,所有錯(cuò)誤的方法調(diào)用都可以被歸結(jié)為非法參數(shù)或者非法狀態(tài),但是,其他還有一些標(biāo)準(zhǔn)異常也被用于某些特定情況下的非法參數(shù)和非法狀態(tài)。如果調(diào)用者在某個(gè)不允許null值的參數(shù)中傳遞了null,習(xí)慣的做法就是拋出NullPointerException,而不是IllegalArgumentException。同樣地,如果調(diào)用者在表示序列下標(biāo)的參數(shù)中傳遞了越界的值,應(yīng)該拋出的就是IndexOutOfBoundsException,而不是IllegalArgumentException
?????? 另一個(gè)值得了解的通用異常是ConcurremModificationException。如果一個(gè)對(duì)象被設(shè)計(jì)為專用于單線程或者與外部同步機(jī)制配合使用,一旦發(fā)現(xiàn)它正在(或已經(jīng))被并發(fā)地修改,就應(yīng)該拋出這個(gè)異常。
??????? 最后一個(gè)值得注意的通用異常是UnsupportedOperationException。如果對(duì)象不支持所請(qǐng)求的操作,就會(huì)拋出這個(gè)異常。與本條目中討論的其他異常相比,它很少用到,因?yàn)榻^大多數(shù)對(duì)象都會(huì)支持它們實(shí)現(xiàn)的所有方法。如果接口的具體實(shí)現(xiàn)沒有實(shí)現(xiàn)該接口所定義的一個(gè)或者多個(gè)可選操作,它就可以使用這個(gè)異常。例如,對(duì)于只支持追加操作的List實(shí)現(xiàn),如果有人試圖從列表中刪除元素,它就會(huì)拋出這個(gè)異常。
以下概括了最常見的可重用異常。
異 常 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 使用場(chǎng)合
IllegalArgumentExccplion 非null的參數(shù)值不正確
lllegalStateException 對(duì)于方法調(diào)用而言,對(duì)象狀態(tài)不合適
NullPointerExceplion 在禁止使用null的情況下參數(shù)值為null
IndexOutOfBoundsException 下標(biāo)參敗值越界
ConcurrentModificationExcepiion 在禁止并發(fā)修改的情況下,檢測(cè)到對(duì)象的并發(fā)修改
UnsupportedOperationExccption 對(duì)象不支持用戶請(qǐng)求的方法
??????? 雖然它們是Java平臺(tái)類庫(kù)中迄今為止最被重用的異常,但是,在條件許可的情況下,其他的異常也可以被重用。例如,如果要實(shí)現(xiàn)諸如復(fù)數(shù)或者有理數(shù)之類的算術(shù)對(duì)象,也可以重用ArithmeticException和NumberFormatException。如果某個(gè)異常能夠滿足你的需要,就不要猶像,使用就是,不過,一定要確保拋出異常的條件與該異常的文檔中描述的條件一致。這種重用必須邊立在語義的基礎(chǔ)上,而不是建立在名稱的基礎(chǔ)之上。而且,如果希望稍微增加更多的失敗-捕獲(failure-capture)信息(見第63條),可以放心地把現(xiàn)有的異常進(jìn)行子類化。
??????? 最后,一定要清楚,選擇重用哪個(gè)異常并不總是那么精確,因?yàn)樯媳碇械摹笆褂脠?chǎng)合”并不是相互排斥的。例如,考慮表示一副紙牌的對(duì)象。假設(shè)有個(gè)處理發(fā)牌操作的方法,它的參數(shù)是發(fā)一手牌的紙牌張數(shù)。假設(shè)調(diào)用者在這個(gè)參數(shù)中傳遞的值大于整副紙牌的剩余張數(shù)。這種情形既可以被解釋為IllegalArgurnemException(handSize參數(shù)的值太大),也可以被解釋為IllegalStateException(相對(duì)于客戶的請(qǐng)求而言,紙牌對(duì)象包含的紙牌太少)。在這個(gè)例子中,感覺IllegalArgumemException要好一些,不過,這里并沒有嚴(yán)格的規(guī)則。