简体   繁体   English

引发检查异常与引发包装的RuntimeException

[英]Throwing Checked Exception vs Throwing a wrapped RuntimeException

At many places, I get several Checked Exceptions like IOException, ParseException, JSONException, etc. I had to make either of 2 choices - 在很多地方,我都会收到多个Checked Exception,例如IOException,ParseException,JSONException等。我必须选择两个选项之一-

  1. Throw the same exception by adding throws at the end of method signature. 通过在方法签名的末尾添加throws引发相同的异常。

  2. Wrap the checked Exception in a RuntimeException(or some custom implementation) and then throw it so that caller doesn't have to add throws clause everywhere and check the exceptions. 将已检查的异常包装在RuntimeException(或某些自定义实现)中,然后将其抛出,以便调用者不必在各处添加throws子句并检查异常。

In the first case, I will have to put throws everywhere, but my client can decide not to die by catching the checkedException and continuing to work. 在第一种情况下,我将不得不在所有地方都抛出异常,但是我的客户端可以通过捕获checkedException并继续工作来决定不死。 In 2nd case, however the RuntimeException may actually force the client to fail, as generally people don't catch Generic/RuntimeExceptions everywhere. 在第二种情况下,RuntimeException实际上可能迫使客户端失败,因为通常人们不会在任何地方捕获Generic / RuntimeExceptions。 Also using 2nd approach makes it easier to use Java 8 lambdas which doesn't work well with Checked Exceptions. 另外,使用第二种方法使使用Java 8 lambda变得更容易,而Java 8 lambda不适用于Checked Exceptions。

Which one of the two is preferred over another and why? 两者中哪一个优于另一个,为什么? Is there any preferred practice to follow? 有什么首选的做法可以遵循吗?

There are two kinds of exceptions: exceptions that can be expected for a call and exceptions that are in principle unexpected (and that the application code probably cannot work around in a meaningful way). 异常有两种:调用可以预期的异常和原则上意外的异常(应用程序代码可能无法以有意义的方式解决)。 For the first kind (eg IOException for a file operation), checked exceptions (with 'throws' at the end of a method signature) are great. 对于第一种(例如,文件操作的IOException),检查异常(方法签名末尾带有“ throws”)非常有用。

For the second situation, it is my opinion that it's fine to wrap it in a RuntimeException for the reasons that you state (not having to add throws everywhere). 对于第二种情况,我认为出于您陈述的理由(不必到处添加抛出),将其包装在RuntimeException中是很好的。 All software should be prepared to catch RuntimeExceptions at the top level as a 'last line of defense', or they accept that a RuntimeException will end the program (which is often acceptable for instance for command line applications). 所有软件都应准备在最高级别捕获RuntimeException作为“最后一道防线”,或者它们接受RuntimeException将结束程序(例如,对于命令行应用程序通常是可以接受的)。

An example for the second situation is that a necessary configuration file is missing. 第二种情况的示例是缺少必要的配置文件。 I would rethrow that IOException as a RuntimeException. 我将那个IOException抛出为RuntimeException。

By the way, there is a third way that is often used: throwing an application-specific exception. 顺便说一句,还有第三种常用的方式:抛出特定于应用程序的异常。 For instance this exception could be called 'MyConfigurationException'. 例如,此异常可以称为“ MyConfigurationException”。 I think this is only useful if an application can catch this exception and handle it intelligently. 我认为这仅在应用程序可以捕获此异常并智能地对其进行处理时才有用。

(1) Throw the same checked exception by adding throws at the end of method signature: (1)通过在方法签名的末尾添加throw来抛出相同的检查异常:

Use this if the caller can recover from the exception or at least has to take some decision/progress based upon that 如果调用者可以从异常中恢复,或者至少必须根据该异常做出决定/处理,请使用此选项

(2) Wrap the checked Exception in a RuntimeException(or some custom implementation): (2)将检查到的异常包装在RuntimeException(或某些自定义实现)中:

Use this if the caller can't recover (Most of the Exceptions in Spring/Hibernate frameworks follow this pattern) 如果调用者无法恢复,请使用此方法(Spring / Hibernate框架中的大多数异常都遵循此模式)

There is a third option, which is to throw the same checked Exception but to 'soften' it. 第三种选择是,抛出相同的选中异常,然后“软化”它。 CheckedExceptions are enforced only at Compile time, and by casting your Exception to a Throwable, you can safely throw it without the compiler complaining. CheckedExceptions仅在编译时强制执行,并且通过将Exception强制转换为Throwable,可以安全地抛出它,而无需编译器抱怨。 Here is an example implementation (available in cyclops-functions a library I contribute to - or you can copy and paste :) ) 这是一个示例实现(在我贡献的库的cyclops函数中可用,或者您可以复制和粘贴:))

UPDATE Simplified ExceptionSoftener class as per Andy Turner's comment. 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