如何为处理其他异常时抛出的异常获取正确链接的堆栈跟踪?

Kid*_*rla 5 java exception-handling stack-trace

假设我正在处理FooExceptionBarException发生.我们假设它们都是未经检查的例外.

我想在stacktrace中看到的是:

com.bar.BarException: Bar Message
    at com.baz.BazCode(BazCode.java:123)
    ...
Caused by: com.foo.FooException: Foo Message
    at com.baz.BazCode(BazCode.java:321)
    ....
Caused by: ...
Run Code Online (Sandbox Code Playgroud)

但是,默认情况下,所有记录FooException都将从堆栈跟踪中删除.例如:

// In a class written by me
/**
  * ...
  * @throws FooException if foo happens
  * @throws BarException if bar happens
  */
public void upperFrame() {
    try {
        foo.doSomething();
    } catch (FooException foo) {
        bar.doSomethingElse();
    }
}

// In class Bar (not written by me)
public void doSomethingElse() {
    if (someConditionWhichHappensToBeTrueInThisScenario()) {
        throw new BarException("Hello Bar World"); // At this point, FooException gets erased from the stack trace
    }
}
Run Code Online (Sandbox Code Playgroud)

如果BarException有一个(message, cause)构造函数,那么我可以遵循一个相当粗略的"手动克隆"过程来实现我的目标:

try {
    foo.doSomething();
} catch (FooException foo) {
    try {
        bar.doSomethingElse();
    } catch (BarException bar) {
        BarException bar2 = new BarException(bar.getMessage(), foo);
        bar2.setStackTrace(bar.getStackTrace());
        throw bar2;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果BarException没有这样的构造函数(例如ClassCastException)那么我可以简化为这样的事情:

try {
    foo.doSomething();
} catch (FooException foo) {
    try {
        bar.doSomethingElse();
    } catch (BarException bar) {
        RuntimeException e = new RuntimeException("com.bar.BarException: " + bar.getMessage(), foo);
        e.setStackTrace(bar.getStackTrace());
        throw e;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是危险的,因为e类型错误,因此可能无法通过更高的帧正确处理.

是否有"最佳实践"方式来处理这种情况?

sp0*_*00m 4

一种解决方案是使用以下Throwable#initCause(Throwable)方法:

bar.initCause(foo);
Run Code Online (Sandbox Code Playgroud)