繁体   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