一些第 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
将被抛出。
限制:
如果出现以下任一情况,此解决方案将不起作用:
- 如果
SomeException
在java.lang
中,因为您无法替换java.lang
类(或参见 Replacing java class?) - 如果第 3 方方法有一个
catch(Throwable e)
(这将是可怕的并且应该促使您忽略完整的第 3 方库)
关于java - 在 Java 中拯救被吞噬的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32358652/