簡體   English   中英

引發檢查異常與引發包裝的RuntimeException

[英]Throwing Checked Exception vs Throwing a wrapped RuntimeException

在很多地方,我都會收到多個Checked Exception,例如IOException,ParseException,JSONException等。我必須選擇兩個選項之一-

  1. 通過在方法簽名的末尾添加throws引發相同的異常。

  2. 將已檢查的異常包裝在RuntimeException(或某些自定義實現)中,然后將其拋出,以便調用者不必在各處添加throws子句並檢查異常。

在第一種情況下,我將不得不在所有地方都拋出異常,但是我的客戶端可以通過捕獲checkedException並繼續工作來決定不死。 在第二種情況下,RuntimeException實際上可能迫使客戶端失敗,因為通常人們不會在任何地方捕獲Generic / RuntimeExceptions。 另外,使用第二種方法使使用Java 8 lambda變得更容易,而Java 8 lambda不適用於Checked Exceptions。

兩者中哪一個優於另一個,為什么? 有什么首選的做法可以遵循嗎?

異常有兩種:調用可以預期的異常和原則上意外的異常(應用程序代碼可能無法以有意義的方式解決)。 對於第一種(例如,文件操作的IOException),檢查異常(方法簽名末尾帶有“ throws”)非常有用。

對於第二種情況,我認為出於您陳述的理由(不必到處添加拋出),將其包裝在RuntimeException中是很好的。 所有軟件都應准備在最高級別捕獲RuntimeException作為“最后一道防線”,或者它們接受RuntimeException將結束程序(例如,對於命令行應用程序通常是可以接受的)。

第二種情況的示例是缺少必要的配置文件。 我將那個IOException拋出為RuntimeException。

順便說一句,還有第三種常用的方式:拋出特定於應用程序的異常。 例如,此異常可以稱為“ MyConfigurationException”。 我認為這僅在應用程序可以捕獲此異常並智能地對其進行處理時才有用。

(1)通過在方法簽名的末尾添加throw來拋出相同的檢查異常:

如果調用者可以從異常中恢復,或者至少必須根據該異常做出決定/處理,請使用此選項

(2)將檢查到的異常包裝在RuntimeException(或某些自定義實現)中:

如果調用者無法恢復,請使用此方法(Spring / Hibernate框架中的大多數異常都遵循此模式)

第三種選擇是,拋出相同的選中異常,然后“軟化”它。 CheckedExceptions僅在編譯時強制執行,並且通過將Exception強制轉換為Throwable,可以安全地拋出它,而無需編譯器抱怨。 這是一個示例實現(在我貢獻的庫的cyclops函數中可用,或者您可以復制和粘貼:))

UPDATE根據Andy Turner的評論簡化了ExceptionSoftener類。

public class ExceptionSoftener {


   public static <T extends Throwable> T softenedException(final T e) {
       uncheck(e);
       return e; //never reached.
   }

   private static <T extends Throwable> void uncheck(Throwable throwable) throws T {
       throw (T) throwable;

   }

 }

   public void methodThrowsIOException(){      
       throw ExceptionSoftener.softenedException(new IOException("checked exception, but no declaration required!"));
   }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM