java - 在 Java 中拯救被吞噬的异常

标签 java exception exception-handling

一些第 3 方库吞下了一个异常:

String getAnswer(){
    try{
        // do stuff, modify instance state, maybe throw some exceptions
        // ...
        return computeAnswer(); 
    }catch (SomeException e){
        return null;
    }
}

只要我想把它改成:

String getAnswer() throws SomeException{
    // do stuff, modify instance state, maybe throw some exceptions
    // ...
    return computeAnswer();
}

我不能,因为该库已经打包到一个 jar 中。那么,有没有办法将异常带回来?

我不需要重新抛出,带有异常和消息的堆栈跟踪也可以。

我认为反射在这里没有帮助,Unsafe 也许?

是的,我知道我可以使用调试器来找出正在发生的事情,但如果我需要运行时的异常来记录日志和类似的东西,那将不会很有用

最佳答案

您可以在没有反射或 AOP 的情况下做到这一点。主要思想是在 SomeException 的构造函数中抛出另一个(未经检查的)异常。有一些限制(请参阅此答案的末尾),但我希望它能满足您的需求。

您需要将 SomeException 替换为新版本(只需在原始包中但在您的 src 目录中创建一个 SomeException.java 文件),例如:

package com.3rdpartylibrary;

public class SomeException extends Exception {
    public static class SomeExceptionWrapperException extends RuntimeException {
        public SomeExceptionWrapperException(final SomeException ex) {
            super(ex.getMessage(), ex);
        }
    }

    public SomeException(final String message) {
        super(message);
        throw new SomeExceptionWrapperException(this); //<=== the key is here
    }
}

必须取消选中 SomeExceptionWrapperException(继承自 RuntimeException 或 Error)。这将是我们的包装器,用于携带 SomeException 穿过丑陋的第 3 方 catch(...)

然后您可以在代码中捕获 SomeExceptionWrapperException(并最终重新抛出原始的 SomeException:

//original, unmodifiable 3rdParty code, here as a example
public String getAnswer() {
    try {
        //some code
        throw new SomeException("a message");
    } catch (final SomeException e) {
        return null;
    }
}

//a wrapper to getAnswer to unwrapp the `SomeException`
public String getAnswerWrapped() throws SomeException {
    try {
        return getAnswer();
    } catch (final SomeExceptionWrapperException e) {
        throw (SomeException) e.getCause();
    }
}

@Test(expected = SomeException.class)
public void testThrow() throws SomeException {
    final String t = getAnswerWrapped();
}

测试将是绿色的,因为原始的 SomeException 将被抛出。

限制:

如果出现以下任一情况,此解决方案将不起作用:

  • 如果 SomeExceptionjava.lang 中,因为您无法替换 java.lang 类(或参见 Replacing java class?)
  • 如果第 3 方方法有一个 catch(Throwable e)(这将是可怕的并且应该促使您忽略完整的第 3 方库)

关于java - 在 Java 中拯救被吞噬的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32358652/

相关文章:

c# - 试着抓。以相同的方式处理多个异常(或失败)

当没有找到记录并且失败时,PHP PDO fetch 返回 FALSE

java - 在 JNI 代码中抛出异常的最佳方法?

java - 在Ubuntu 14.04 hadoop 2.6版的单节点群集设置中运行hadoop程序

c++ - cv::Rect 的异常处理

java - 入门教程(错误)

c++ - 构造函数异常和内存泄漏

json - 为什么我的 req.flash 不起作用?

java - 使用 Java 从 LDAP 检索 sidHistory

java - 确认文本框已禁用