简体   繁体   中英

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 -

  1. Throw the same exception by adding throws at the end of method signature.

  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.

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. In 2nd case, however the RuntimeException may actually force the client to fail, as generally people don't catch Generic/RuntimeExceptions everywhere. Also using 2nd approach makes it easier to use Java 8 lambdas which doesn't work well with 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.

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). 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).

An example for the second situation is that a necessary configuration file is missing. I would rethrow that IOException as a 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'. 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:

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):

Use this if the caller can't recover (Most of the Exceptions in Spring/Hibernate frameworks follow this pattern)

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. Here is an example implementation (available in cyclops-functions a library I contribute to - or you can copy and paste :) )

UPDATE Simplified ExceptionSoftener class as per Andy Turner's comment.

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!"));
   }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM