将信息添加到异常中

13

我想要向堆栈跟踪/异常中添加信息。

目前我的代码大致如下,我真的很喜欢它:

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at com.so.main(SO.java:41)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke

不过我想捕获那个异常并添加额外的信息,同时仍保留原始的堆栈跟踪。

例如,我想要这样的结果:

Exception in thread "main" CustomException: / by zero (you tried to divide 42 by 0)
    at com.so.main(SO.java:41)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke

基本上我想捕获ArithmeticException并重新抛出一个CustomException(在这个例子中添加“你试图将42除以0”),同时仍保留原始ArithmeticException的堆栈跟踪。

在Java中,正确的方法是什么?

以下代码是否正确:

try {
     ....
} catch (ArithmeticException e) {
     throw new CustomException( "You tried to divide " + x + " by " + y, e );
}

如果你不是抛出异常的人,你怎么可能知道它的具体情况呢? - Falmarri
@Falmarri:我不知道具体细节,但我可以添加其他信息,比如方法参数。我在问题的末尾添加了一个示例。 - NoozNooz42
通常这些信息只有在调试时才有用。您还可以尝试使用调试器来调试程序,并在异常处设置断点。当抛出异常时,您将看到导致它的条件。 - Peter Lawrey
2个回答

14
你也可以这样做:
try {
     ....
} catch (ArithmeticException e) {
     ArithmeticException ae = new ArithmeticException( "You tried to divide " + x + " by " + y+" "+e.getMessage());
     ae.setStackTrace(e.getStackTrace());
     throw ae;
}

这将给你“隐形”的异常 :-)

更新[2012年9月27日]:

在Java 7中:另一个酷炫的技巧是:

try {
    ...
} catch (ArithmeticException e) {
    e.addSuppressed(new ArithmeticException( "You tried to divide " + x + " by " + y));
    throw e;
}

+1也是这样的吗?你所说的“不可见”,是指只有一个堆栈跟踪而不是两个吗? - NoozNooz42
1
我无法编辑你的答案(我的声望不够),但我认为你剪切/粘贴并在创建ArithmeticException的行的末尾留下了“,e *”,应该将其删除。 - NoozNooz42
1
是的,只会有一个堆栈跟踪。感谢您注意到了这个错误。 - Pat
1
我不能编辑你的答案,因为我没有足够的声望 并且 因为那不是我的答案。尽管你只有 667 声望,但你始终可以编辑自己的答案,所以如果你想要修复它的话,可以自行修改 :) - NoozNooz42

14

是的,你可以在Java中像这样嵌套异常,在Java 1.4版本之后,我经常使用此功能。请参见http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Throwable.html

当某人从你的自定义异常中打印堆栈跟踪时,它将显示CustomException的堆栈跟踪以及嵌套的ArithmeticException的堆栈跟踪。你可以任意深度嵌套异常。


+1,非常感谢。很有趣看到它已经存在很长时间了 :) - NoozNooz42
2
链接失效了 [难过的表情] - meawoppl
这是一个有帮助的回答。我已经知道你可以在彼此之间嵌套异常,但我不明白如果您想要在深度嵌套的异常中包含信息,这已经为您完成了。我注意到在打印的堆栈跟踪中,每个异常的消息都是在异常名称之后打印的。例如:Caused by: java.lang.IllegalArgumentException: you tried to divide 1.0 by 0. 我习惯于 Go 编程,那里您必须在为每个错误创建的字符串中自己包含此信息,以便在返回包装错误时使用。 - Matt Welke

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