How to wrap checked exceptions but keep the original runtime exceptions in Java

后端 未结 7 2265
一向
一向 2020-12-15 16:36

I have some code that might throw both checked and runtime exceptions.

I\'d like to catch the checked exception and wrap it with a runtime exception. But if a Runtim

相关标签:
7条回答
  • 2020-12-15 16:56

    You can rewrite the same using instanceof operator

    try {
        // some code that can throw both checked and runtime exception
    } catch (Exception e) {
        if (e instanceof RuntimeException) {
            throw e;
        } else {
            throw new RuntimeException(e);
        }
    }
    

    However, your solution looks better.

    0 讨论(0)
  • 2020-12-15 16:57

    I use a "blind" rethrow to pass up checked exceptions. I have used this for passing through the Streams API where I can't use lambdas which throw checked exceptions. e.g We have ThrowingXxxxx functional interfaces so the checked exception can be passed through.

    This allows me to catch the checked exception in a caller naturally without needing to know a callee had to pass it through an interface which didn't allow checked exceptions.

    try {
      // some code that can throw both checked and runtime exception
    
    } catch (Exception e) {
      throw rethrow(e);
    }
    

    In a calling method I can declare the checked exception again.

    public void loadFile(String file) throws IOException {
       // call method with rethrow
    }
    

    /**
     * Cast a CheckedException as an unchecked one.
     *
     * @param throwable to cast
     * @param <T>       the type of the Throwable
     * @return this method will never return a Throwable instance, it will just throw it.
     * @throws T the throwable as an unchecked throwable
     */
    @SuppressWarnings("unchecked")
    public static <T extends Throwable> RuntimeException rethrow(Throwable throwable) throws T {
        throw (T) throwable; // rely on vacuous cast
    }
    

    There is a lot of different options for handling exceptions. We use a few of them.

    https://vanilla-java.github.io/2016/06/21/Reviewing-Exception-Handling.html

    0 讨论(0)
  • 2020-12-15 16:58

    Not really.

    If you do this a lot, you could tuck it away into a helper method.

    static RuntimeException unchecked(Throwable t){
        if (t instanceof RuntimeException){
          return (RuntimeException) t;
        } else if (t instanceof Error) { // if you don't want to wrap those
          throw (Error) t;
        } else {
          return new RuntimeException(t);
        }
    }
    
    try{
     // ..
    }
    catch (Exception e){
       throw unchecked(e);
    }
    
    0 讨论(0)
  • 2020-12-15 17:04

    I generally use the same type of code structure, but condense it down to one line in one of the few times a ternary operator actually makes code better:

    try {
      // code that can throw
    }
    catch (Exception e) {
      throw (e instanceof RuntimeException) ? (RuntimeException) e : new RuntimeException(e);
    }
    

    This does not require additional methods or catch blocks which is why I like it.

    0 讨论(0)
  • 2020-12-15 17:11

    The problem is that Exception is too broad. You should know exactly what the possible checked exceptions are.

    try {
        // code that throws checked and unchecked exceptions
    } catch (IOException | SomeOtherException ex) {
        throw new RuntimeException(ex);
    }
    

    The reasons why this wouldn't work reveal deeper problems that should be addressed instead:

    If a method declares that it throws Exception then it is being too broad. Knowing that "something can go wrong" with no further information is of no use to a caller. The method should be using specific exception classes in a meaningful hierarchy, or using unchecked exceptions if appropriate.

    If a method throws too many different kinds of checked exception then it is too complicated. It should either be refactored into multiple simpler methods, or the exceptions should be arranged in a sensible inheritance hierarchy, depending on the situation.

    Of course there can be exceptions to the rule. Declaring a method throws Exception can be perfectly reasonable if it's consumed by some kind of cross-cutting framework (such as JUnit or AspectJ or Spring) rather than comprising an API for others to use.

    0 讨论(0)
  • 2020-12-15 17:14

    I have a specially compiled .class file containing the following:

    public class Thrower {
        public static void Throw(java.lang.Throwable t) {
            throw t;
        }
    }
    

    It just works. The java compiler would normally refuse to compile this, but the bytecode verifier doesn't care at all.

    The class is used similar to Peter Lawrey's answer:

    try {
      // some code that can throw both checked and runtime exception
    
    } catch (Exception e) {
        Thrower.Throw(e);
    }
    
    0 讨论(0)
提交回复
热议问题