1. 程式人生 > >java異常的捕獲與丟擲原則

java異常的捕獲與丟擲原則

在可能會出現exception的地方,要使用try-catch或者throws或者兩者都要。我的判斷依據是:如果對可能出現的exception不想被外部(方法的呼叫者)知道,就在方法內部try-catch掉這個exception;如果希望外部知道,則在catch到之後把exception直接丟擲或者丟擲自定義的exception。   
一、異常的種類   
java異常可以分成兩大類:Exception和RuntimeException(雖然RuntimeException是從Exception繼承的)。exception異常代表“無法避免的異常” 如io異常   往往這類異常是由於外部原因造成的,程式本身無法保證他們不發生,所以這類異常必須捕獲。如果在函式內部無法處理這個異常必須再次丟擲(在函式後面用throws語句),如果什麼都不做就出現編譯錯誤。 

runtimexception是指“可以避免的異常”,如 null引用異常,這類異常都是由程式內部原因造成的,是可以避免的。對於這類異常可以忽略他們,但一旦發生程式就會異常終止。這類異常對debug非常有幫助,當然,如果需要也可以catch。 

另外,有些地方即使不會有exception,但是從商業邏輯上是錯誤的、非預期的,也可以丟擲user exception。例如,使用者輸入非法,bank account非法透支等等。 

二、主要原則   
處理意外的一個重要原則,就是要麼處理,要麼接著拋,決不能吃掉(You either handle it, or throw it. You don’t eat it.)這就是說,當你捕獲一個異常之後,必須決定是否立即處理這個異常,或者繼續丟擲這個異常(或者另一個自定義異常),以便由呼叫的客戶端捕獲之。當客戶端捕獲到以後,又會繼續進行類似的判斷。 


一般來說,GUI端是要處理異常的,比如JSP捕獲到異常之後,需要先是給使用者一個友好的出錯資訊,而不要給出系統的出錯資訊。系統的出錯資訊一方面不太友好,另一方面提供了太多的系統資訊,容易被惡意使用者用來攻擊系統。 

換句話說,所有的異常最終必須有一個終極的處理者,這就是GUI。至於中間的環節,比如在伺服器端執行的JavaBean是否要處理捕獲到的異常,還是繼續丟擲所捕獲的異常,需要視具體情況處理。   

除非你想把異常處理的責任交給呼叫者,一般不用throws。 比如你要讀入一些檔案,如果你想通知呼叫者,讓呼叫者決定如何處理這個異常,你就把這個異常throws給呼叫者;如果你知道應該如何處理這個異常,或者你想把異常馬上解決,你可以就地catch她。 


這完全取決於你想把異常自己立即處理還是想把處理責任返回給呼叫者。取決於你的程式的結構和要求。   
需要注意的有: 
1、如果無法處理某個異常,那就不要捕獲它。   
2、如果捕獲了一個異常,請不要胡亂處理它。   
3、儘量在靠近異常被丟擲的地方捕獲異常。   
4、在捕獲異常的地方將它記錄到日誌中,除非您打算將它重新丟擲。   
5、按照您的異常處理必須多精細來構造您的方法。   
6、需要用幾種型別的異常就用幾種,尤其是對於應用程式異常。   

三、異常巢狀和捕獲適當的異常 

按照Java語言的定義,所謂異常(Exception)指的就是向呼叫方法(calling method)表示發生非正常情況的習慣方式。下面討論兩種在處理異常時可茲利用的技術:異常巢狀和捕獲適當的異常。 

異常巢狀   
你在試圖捕獲異常並打算扔出異常時該採取什麼措施呢?同時,你希望原始的異常資訊可用嗎?   

要回答以上的問題你不妨嘗試一下NestedException類。具體的程式設計並不難,唯一要做的無非是利用構造器並且過載printStackTrace()以便顯示出正確的資料。 

此外,你還應當考慮封裝Throwable而非Exception類來建立更具有重用性的元件。之後,你可以建立NestedRuntimeException變數封裝Throwable但無需對其進行宣告。 

捕獲適當的異常 
正確地處理異常並不是一項輕鬆的任務,這是因為異常的處理有時會導致程式出現其他不明行為。不過,以下三條規則可以幫助你避免錯誤處理異常所可能遭遇的風險。 

規則 #1: 總是捕獲扔出異常的型別而不要理睬異常的超類。 為了遵守通常的程式碼習慣,你可以採用Exception類的大寫字母作為變數名,如下所示:   
    catch(FileNotFoundException fnfe)   
以及 
    catch(SQLException sqle) 

規則 # 2: 決不讓catch塊留空。在很多情況下雖然確實編寫了try/catch塊但在程式碼的catch部分卻什麼都沒有做。或者,如果採用了日誌API(Logging API),那麼請編寫程式碼把異常寫到日誌中。 

規則 # 3: 決不扔出Exception基類的例項。開發人員應當總是扔出自己建立的異常類。 

扔出異常的API很難處理。在宣告方法扔出java.lang.Exception的情況下,所有的問題都會強加在API使用者的頭上,這樣他們就無法以一種專業的程式設計方式來處理異常。通過為扔出API宣告Exception類的子類這一舉措,API開發人員就可以減輕使用者的負擔。 

以上提到的兩種技術在處理異常時還可能用得更好、更適當。巢狀技術令異常扔到另一異常的內部,而捕獲適當的異常令程式除錯大大簡化。