如何包装已检查的异常但在Java中保留原始运行时异常

Ali*_*aka 25 java runtimeexception checked-exceptions

我有一些代码可能会抛出已检查和运行时异常.

我想捕获已检查的异常并将其包装为运行时异常.但是如果抛出RuntimeException,我不必将它包装起来,因为它已经是运行时异常.

我的解决方案有点开销,并不"整洁":

try {
  // some code that can throw both checked and runtime exception
} catch (RuntimeException e) {
  throw e;
} catch (Exception e) {
  throw new RuntimeException(e);
}
Run Code Online (Sandbox Code Playgroud)

想要更优雅的方式吗?

Pet*_*rey 28

我使用"盲目"重新抛出来传递已检查的异常.我已经使用它来传递Streams API,我不能使用抛出已检查异常的lambdas.例如,我们有ThrowingXxxxx功能接​​口,因此可以传递经过检查的异常.

这允许我自然地在调用者中捕获已检查的异常,而不需要知道被调用者必须通过不允许检查异常的接口传递它.

try {
  // some code that can throw both checked and runtime exception

} catch (Exception e) {
  throw rethrow(e);
}
Run Code Online (Sandbox Code Playgroud)

在调用方法中,我可以再次声明已检查的异常.

public void loadFile(String file) throws IOException {
   // call method with rethrow
}
Run Code Online (Sandbox Code Playgroud)
/**
 * 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
}
Run Code Online (Sandbox Code Playgroud)

处理异常有很多不同的选择.我们使用其中的一些.

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

  • "Sneaky"是这个半官方的名字:) (8认同)
  • @ AlikElzin-kilaka是的,这种语法只适用于Java 8中的新推理规则.对于Java 7,需要使用两种方法的更长的习惯用法. (5认同)
  • 所以这实际上会在运行时抛出IOException(来自`rethrow`),但是编译器认为它是一个未经检查的异常(因为你说你会这样抛出它,即使演员被删除了)? (2认同)
  • @Thilo在运行时,JVM的checked和unchecked之间没有区别,并且有一些方法可以"欺骗"在运行时工作的编译器.使用泛型的演员是我觉得最简单的. (2认同)

shm*_*sel 18

番石榴Throwables.propagate()的确做到了这一点:

try {
    // some code that can throw both checked and runtime exception
} catch (Exception e) {
    throw Throwables.propagate(e);
}
Run Code Online (Sandbox Code Playgroud)

更新:此方法现已弃用.有关详细说明,请参阅此页面.


Thi*_*ilo 5

并不是的.

如果你经常这么做,你可以把它塞进一个辅助方法.

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);
}
Run Code Online (Sandbox Code Playgroud)