【问题标题】:How to re-throw a Throwable?如何重新抛出 Throwable?
【发布时间】:2021-06-20 19:37:42
【问题描述】:

考虑这段代码:

@Test(expected = NullPointerException.class)
public void testSaveEmptyApplication() {
    try {
        Application application = new Application();
        Application result = applicationService.save(application);
    } catch (Exception e) {
        if(e instanceof UncheckedServiceException) {
            throw e.getCause(); // java.lang.Throwable, compiler error
        }
    }
}

如何重新抛出 Throwable?

【问题讨论】:

标签: java exception try-catch throw


【解决方案1】:

我能想到的一个解决方案是:

catch 子句是:

try {
  // ...
} catch (Exception e) {
    if(e instanceof UncheckedServiceException) {
        if(e.getCause() instanceof NullPointerException) {
            throw new NullPointerException(e.getCause().getMessage());
       }
    }
}

否则像这样更改方法签名:

public void method() throws Throwable {
 // ...
}

【讨论】:

  • 这引发了一个新异常......与原始“原因”异常的堆栈跟踪不同。
【解决方案2】:

问题是testSaveEmptyApplication 没有声明为抛出任何检查异常。但是e.getCause() 返回Throwable,这是一个检查异常。因此,您在示例代码中所做的是违反 Java 的已检查异常规则。

如果您知道原因确实是RuntimeException,那么您可以这样做

throw (RuntimeException) e.getCause();

注意事项:

  • 但是,如果您的假设不正确并且原因异常的实际类是已检查异常,则上述将导致(全新的)ClassCastException 压缩您试图重新抛出的原因异常。

  • 如果原因是Error,上述内容也会中断,但您可以处理它;比如这样的。

     Throwable cause = e.getCause();
     if (cause instanceof RuntimeException) {
         throw (RuntimeException) cause;
     } else if (cause instanceof Error) {
         throw (Error) cause;
     } else {
         throw new AssertionError("Unexpected exception class", cause);
     }
    
  • 如果您希望能够重新抛出已检查的异常,则必须在方法签名中声明它们。完成后,您可以按照上述模式区分并抛出它们。

这有点麻烦。但这是您为首先包装异常而付出的代价。

【讨论】:

    猜你喜欢
    • 2014-08-16
    • 1970-01-01
    • 2012-06-29
    • 1970-01-01
    • 1970-01-01
    • 2018-09-15
    • 1970-01-01
    • 2023-02-04
    • 2021-04-01
    相关资源
    最近更新 更多