2012-08-05 108 views
3

我的工作在哪裏的過程中繼續這樣下去UI的應用程序 - >後臺處理 - >結果到UI。Java異常處理策略

在我的代碼,我已經處理使用try,抓我的異常。但是在代碼中,我有很多重複的異常,可能會在不同的類中引發相同的異常。

所以,我打算做一個異常處理策略,這樣,當異常被拋出,必須被重定向到單獨的異常處理代碼(類似於單獨的自定義異常處理庫類)。所以它不應該在我的業務邏輯裏面。

可能有人建議我如何實現它,無論是其最好的辦法來處理我的異常?或者任何人都可以建議我使用異常處理技術來完成除我以外的其他操作?

謝謝您,期待您的回覆。

+0

也許這個鏈接很有用 http://stackoverflow.com/questions/11825852/exception-handling-strategy-reuse-exception-codes – 2012-08-08 07:59:40

回答

6

如果您拋出過低級別的異常,則可以在上面幾次調用它們,然後使用用戶友好的消息將錯誤包裝爲更一般和有意義的異常,然後再次將它們丟棄到最高級別,然後停止應用程序並以某種方式查看它們(例如在標籤上)給用戶。

Effective Java (item 61)

它是令人不安當一個方法拋出具有與要執行的任務不 明顯的連接異常。當一個方法傳播一個由較低級別的抽象拋出的異常時,這經常發生在 。這不僅令人不安,而且會污染上層的API 及其實施細節。如果實施在後續版本中高層變動 ,例外 它拋出也可能發生變化,有可能打破現有的客戶 程序。

爲了避免這個問題,高層應該捕獲低層次的異常,並取而代之,這些異常在高層抽象方面可以解釋爲 。這個成語被稱爲 異常轉換:

// Exception Translation 
try { 
    // Use lower-level abstraction to do our bidding 
    ... 
} catch(LowerLevelException e) { 
    throw new HigherLevelException(...); 
} 

雖然異常轉換要優於從較低層的異常傳播盲目,它不應該被過度使用。其中 可能,通過確保較低級別的方法成功,處理來自較低層的異常的最佳方法是通過 來避免它們。有時候你可以通過檢查高層方法的參數 的有效性,然後將它們傳遞給較低層。

如果無法防止較低層的異常,下一個最好的做法是讓較高層靜靜地圍繞這些異常工作,將較高級別方法的調用者與較低級別問題隔離開來。在這種情況下,可能需要使用 java.util.logging等合適的日誌記錄功能 來記錄異常。這使管理員可以調查 問題,同時將客戶端代碼和最終用戶隔離開來。總之,如果防止或處理來自低層的異常是不可行的,則使用異常翻譯,除非下層的方法確保所有異常都適合 到更高層次。 Chaining提供了兩全其美的方法: 允許您拋出適當的更高級別的異常,而 捕獲失敗分析的根本原因(Item 63)。

+0

非常感謝你的回覆。在我的代碼中,我有不同的例外nullpointer,numberformat,數據庫連接異常等....對於數據庫連接異常,我需要嘗試最多三次重新連接數據庫,如果不是,那麼只有異常必須拋出。我如何需要組織這些不同的例外? – user1577729 2012-08-05 19:03:59

+0

@ user1577729如果您可以嘗試處理它們(重新連接到數據庫)**這樣做**。如果你不能 - 例如NPE或numberFormat - 它取決於異常來源 - 如果它是用戶輸入的數據,並且可立即重新輸入 - 馬上通知用戶。如果用戶需要付出一些努力 - 最好記錄每個不會完全壓制應用程序的異常,並稍後顯示發現錯誤的信息。 – dantuch 2012-08-05 19:13:32

+0

@ user1577729在大多數情況下,工作應用程序(運行期間有一些例外情況)比值得停止的應用程序多得多,並通知有關發生的某些錯誤。真正的軟件有錯誤,但即使如此 - 如果它工作,它可以做一些工作,這是值得更多,然後沒有:) – dantuch 2012-08-05 19:15:40

5

從有效的Java(約書亞·布洛克)

  • 僅用於特殊情況例外(從來沒有使用普通的控制流)
  • 使用檢查可恢復條件和運行時異常的編程錯誤異常。 checked異常的
  • 避免不必要的使用

避免檢查的異常。

http://www.mindview.net/Etc/Discussions/CheckedExceptions http://www.ibm.com/developerworks/java/library/j-jtp05254/index.html

  • 經過異常通常被認爲是由許多有缺陷的功能。這不是一個壞主意,但人們並不真正瞭解如何使用它們。
  • 像Spring,Hibernate這樣的Java框架......它們大都拋出未經檢查的異常。
  • C#沒有有意實現檢查的異常。斯卡拉也沒有。
  • 這不是因爲它沒有被檢查,你無法捕捉它。
  • 這不是因爲它沒有被檢查,你不能翻譯它(包裝它)
  • 這不是因爲它沒有被檢查,它不是合同的一部分。事實上,你可以聲明該方法拋出未經檢查的異常。
  • 經過異常增加客戶端和圖書館瞭解

其中很重要的一點是,任何一段代碼可以產生一個異常之間的耦合。 這並不是因爲某個方法聲明拋出IOException,而是拋出了其他異常。它可以拋出任何其他運行時異常(通用或自定義)。隨着檢查的異常,開發商傾向於認爲相反,並認爲趕上IOException異常將處理所有的例外情況,但事實並非如此!


編譯時的功能只

只有編譯器會告訴你,當你忘記趕上或重新拋出檢查異常。在運行時,沒有區別。

這意味着,通過使用類型擦除的技巧,你可以拋出一個checked異常,甚至無需它是方法合同的一部分。

您可以找到此招的例子是被稱爲SneakyTrow這裏: https://stackoverflow.com/a/4890489/82609

龍目島還提供了一個@SneakyThrow註釋穿上方法,使您不必在方法簽名申報檢查的異常。


只有使用checked異常時,你的類客戶端可以或許從異常中恢復。

這是Sun的建議。

基本上,連接數據庫的嘗試會拋出一個檢查異常,並且重試策略代碼將在連接嘗試中捕獲這些檢查的異常。當超過重試次數時,重試策略將拋出未經檢查的異常,這意味着它不是可恢復的異常,因爲恢復策略已經嘗試過。 您可以使用Spring RetryTemplate。


避免異常代碼

的異常類型應該是足夠的流量控制決策。解析異常或流量控制只會創建無用的代碼。添加更多異常類型,就像您有異常代碼一樣。


快速失敗

讓所有的不可恢復的例外是投擲到IHM層。 如果您使用聲明已檢查異常的框架並且您沒有針對它們的恢復策略,請不要猶豫,將它們包裝爲未經檢查的異常。

如果你不能恢復,那麼你不應該「抓住並記錄」。或者更糟的是,你不應該「捕獲並返回null」。這會產生不一致的軟件,您可能會在程序中稍後提出另一個異常,但您將無法理解其原因。返回null只會在稍後創建一個NullPointerException。

IHM層技術可能有一個異常處理程序/映射器。 Web IHM圖層具有異常映射器,因此您可以說「此異常會產生404錯誤」。


功能法

的信息:在函數式語言它經常被認爲是不好的做法,用於流量控制的異常。 我們通常返回「增強類型」,比如Either [Error,MyResultType],而不是拋出異常。

返回的實例可能是錯誤或成功,返回的成功是MyResultType實例。


例外是不高性能用於流控制

創建例外具有成本(創建堆棧跟蹤)。它使用if,else ...的成本遠遠高於正常流量。如果可以避免它們,請不要將它們用於流量控制。

基本上,大多數情況下你總是可以避免它們,但在Java中,在某些情況下使用它們可能更方便。在函數式語言中,任何monad都可以再次提供幫助。


使用斷言

如果你的程序的東西,假設由開發商是真實的,使用斷言,讓你保證你的說法是真實的。 看看番石榴前提條件: https://code.google.com/p/guava-libraries/wiki/PreconditionsExplained

或者你可以使用Java本機斷言,或一些自定義代碼。 這有助於快速失敗。