找出被捕获的异常

4

原始问题

给定以下方法,它是一个库的一部分(因此无法编辑)(A()也是私有的,因此不能在m()之外调用):

void m() {
    try {
        A();
    } catch (Exception e) {
        B();
        throw e;
    }
}

在调用m()时,A()生成了一个异常e,然后执行B()。然而,B()也抛出了一个异常,该异常被传递了上去(而不是e,后者会在下一行被传递上去)。
有没有可能找到e这个异常呢?也许可以使用一些智能的反射或多线程暂停-继续的方法?
为什么我选择最佳答案以及其他有帮助的信息
Makoto的答案:

e丢失了,因为任何抛出的异常都会导致执行突然完成。

是我的问题的正确答案(即无法在程序中检索e异常)。
然而,我想指出Sean Patrick Floyd的评论:

如果你不能改变代码,那么唯一的机会就是使用调试器,在catch块内设置断点。

以及Pinkie Swirl的评论:

请注意,通过调试仍然可以看到e及其信息(堆栈跟踪等)

实际上帮助我解决了我的问题:通过调试器(我遇到的异常是SQLException,所以我真的需要知道它是什么才能解决我的问题)。

1
如果您无法更改代码,那么您唯一的机会就是使用调试器并在catch块内设置断点。但除此之外,如果不更改代码,您将永远看不到该异常。 - Sean Patrick Floyd
2个回答

3

e丢失了,因为任何抛出的异常都会导致执行突然完成

考虑以下(有效的)代码:

void m() throws Exception {
    try {
        A();
    } catch (Exception e) {
        B();
        throw e;
    }
}

private void B() {
    throw new RuntimeException("No!!!!");
}

private void A() throws Exception {
    throw new RuntimeException("Do I make it??");
}

调用 B() 语句将导致整个 m() 方法突然终止,因为抛出了异常。这意味着当前代码块中的 e 不再可访问。

从另一个角度看,如果你在 catch 内翻转语句的顺序...

void m() throws Exception {
    try {
        A();
    } catch (Exception e) {
        throw e;
        B();
    }
}

如果编译器可以保证 B() 永远不会被执行,那么调用 B() 的语句将被视为无法到达。同样的情况也发生在这里,只是有一个小细节:编译器无法确定在 B() 执行期间是否绝对保证抛出异常。


1
请注意,通过调试,仍然可以看到变量 e 及其信息(堆栈跟踪等)。 - Pinkie Swirl
@PinkieSwirl:是的,但是catch语句内部没有任何处理e的语句。它实际上被忽略了。 - Makoto
是的,我知道,只是想补充一下,如果楼主有这个选项的话,因为他在问题中没有指明。 - Pinkie Swirl
@PinkieSwirl 如果您所说的调试是指在m()内部插入或更改任何内容,那么不行。但我有监视执行m()Thread的选项。也许我能做些什么吗?是否可以获取Thread中最后抛出的Exception或当前正在捕获的Exception - Infima
1
调试是指以调试模式执行代码,例如您可以设置断点并逐步执行代码。 - Pinkie Swirl
显示剩余3条评论

1
在大多数调试器(例如 Intellij)中,你可以设置一个断点以便在异常被抛出时中断程序,而不是处理异常时中断。
你还可以过滤该抛出语句的类或其他条件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接