天天看點

Java 基礎【14】 異常與自定義異常

Java 基礎【14】 異常與自定義異常

   Throwable 是所有異常類的基類,它包括兩個子類:Exception 和 Error。

a. 錯誤 (Error)

   錯誤是無法難通過程式來解決的,是以程式不應該抛出這種類型的對象。

   如果出現了這樣的内部錯誤,除了通知給使用者,并盡力使程式安全地終止。當然這類情況是很少出現的(上圖 OutOfMemoryError)。

a.非運作時異常(Checked Exception)

   Java 中凡是繼承自 Exception 但不是繼承自RuntimeException 的類都是非運作時異常(上圖 NoSuchMethodException)。

b.運作時異常(Runtime Exception)

   RuntimeException 類直接繼承自 Exception 類,稱為運作時異常。

   Java中所有的運作時異常都直接或間接的繼承自 RuntimeException (上圖 NullPointerException)。

a.對應非運作時異常,必須對其進行處理。處理方式有兩種:

使用 try…catch…finally 語句塊進行捕獲

在産生異常的方法所在的方法聲明 throws Exception

b.對于運作時異常,可以不對其進行處理,也可以對其進行處理。一般情況下都不對其進行處理。

   在使用Java API的方法時會産生異常,由于實際的需要,我們需要建立和使用自定義異常。使用全新的異常類,應用到系統程式中。

   在介紹自定義異常時,首要先談談什麼要使用自定義異常,使用自定義異常的好處。

   建立自定義異常是為了表示應用程式的一些錯誤類型,為代碼可能發生的一個或多個問題提供新的含義;

   可以顯示代碼多個位置之間的錯誤的相似處,也可區分代碼運作時可能出現的相似問題的一個或多個錯誤,或給出應用程式中一組錯誤的特殊含義。

   伺服器的基本作用是處理與客戶機的通信,若使用标準Java API 使編寫的代碼在多個位置抛出 IOException。

   在設定伺服器、等待客戶機連接配接和擷取通訊流時,可抛出 IOException。

   在通信期間及試圖斷開連接配接時,也會抛出IOException。

   簡而言之,伺服器的各個部分都是引發 IOException,但對于伺服器而言,這樣 IOException 意義不盡相同。

   雖然由同一異常類型表示,但與各個異常先關的業務含義存在差異,報告和恢複操作也不相同。

   是以,可以将一個異常與伺服器配置、啟動問題關聯,将另一個異常與客戶機通訊的實際行動關聯,将第三個異常與伺服器關閉任務關聯等。

   為此,我們需要使用自定義異常來定為問題,定位問題與異常實際準确的位置。

   自定義異常類可以繼承 Throwable 類或者 Exception 類,自定義異常類之間也可以有繼承關系。

   需要為自定義異常類設計構造方法,以友善構造自定義異常對象。

   在繼承任何異常時,将自動繼承 Throwable 類的一些标準特性,如:錯誤消息/棧跟蹤/ 異常包裝....

   若要在異常中添加附加資訊,則可以為類添加一些變量和方法。

a.首先繼承異常類 Exception

   本例示範的自定義異常沒有按照業務類型來命名,而是建立一個通用異常類。

   以 retCd 來差別發生異常的業務類型與發生位置,當然對于具體的 retCd 值,事先必須有具體的規定或說明。

Java 基礎【14】 異常與自定義異常
Java 基礎【14】 異常與自定義異常

b. 其次聲明方法抛出自定義異常

   為了使用自定義異常,必須通知調用代碼的類:要準備處理這個異常類型。

   為此,聲明一個或多個方法抛出異常。找到異常發生點,建立異常并加上關鍵字 throw。

Java 基礎【14】 異常與自定義異常
Java 基礎【14】 異常與自定義異常

c.捕獲異常之後的操作

Java 基礎【14】 異常與自定義異常
Java 基礎【14】 異常與自定義異常

 a.記得釋放資源

   如果你正在用資料庫或網絡連接配接的資源,要記得釋放它們。

   如果你使用的 API 僅僅使用 unchecked exception,你應該用完後釋放它們,使用 try-final。

Java 基礎【14】 異常與自定義異常
Java 基礎【14】 異常與自定義異常

   在這個例子中,finally 關閉了連接配接,如果關閉過程中有問題發生的話,會抛出一個 RuntimeException。

b.不要使用異常控制流程

   生成棧回溯是非常昂貴的,棧回溯的價值是在于調試。

   在流程控制中,棧回溯是應該避免的,因為用戶端僅僅想知道如何繼續。

   下面的代碼,一個自定義的異常 MaximumCountReachedException,用來控制流程。

Java 基礎【14】 異常與自定義異常
Java 基礎【14】 異常與自定義異常

   useExceptionsForFlowControl()使用了一個無限的循環來遞增計數器,直至異常被抛出。

   這樣寫不僅降低了代碼的可讀性,而且代碼效率低下。

c. 不要忽略異常

   當一個 API 方法抛出 checked exception 時,它是要試圖告訴你需要采取某些行動處理它。

   如果它對你來說沒什麼意義,不要猶豫,直接轉換成 unchecked exception 抛出,千萬不要僅僅用空的{}catch 它,然後當沒事發生一樣忽略它。

d. 不要 catch 最高層次的 exception

   Unchecked exception 是繼承自 RuntimeException 類的,而 RuntimeException 繼承自 Exception。如果 catch Exception 的話,你也會 catch RuntimeException。

   上面的代碼會忽略掉 unchecked exception。

e. 僅記錄 exception 一次

   對同一個錯誤的棧回溯(stack trace)記錄多次的話,會讓程式員搞不清楚錯誤的原始來源。是以僅僅記錄一次就夠了。

   總結:這裡是我總結出的一些異常處理最佳實施方法。我并不想引起關于 checked exception 和 unchecked exception 的激烈争論。

   你可以根據你的需要來設計代碼。我相信,随着時間的推移,你會找到些更好的異常處理的方法的。

本文轉自Orson部落格園部落格,原文連結:http://www.cnblogs.com/java-class/p/7458544.html,如需轉載請自行聯系原作者