在Java中重新抛出异常而不丢失堆栈跟踪

在c#中,我可以使用throw;语句在保留堆栈跟踪的同时重新抛出异常:

try
{
...
}
catch (Exception e)
{
if (e is FooException)
throw;
}

在Java (这不会丢失原始的堆栈跟踪)中有类似的东西吗?

323853 次浏览

在Java中几乎是一样的:

try
{
...
}
catch (Exception e)
{
if (e instanceof FooException)
throw e;
}
catch (WhateverException e) {
throw e;
}

将简单地重新抛出您捕获的异常(显然,周围的方法必须通过其签名等允许这样做)。异常将维护原始堆栈跟踪。

在Java中,你只是抛出你捕获的异常,所以throw e而不仅仅是throw。Java维护堆栈跟踪。

我更喜欢:

try
{
...
}
catch (FooException fe){
throw fe;
}
catch (Exception e)
{
// Note: don't catch all exceptions like this unless you know what you
// are doing.
...
}

就像这样

try
{
...
}
catch (FooException e)
{
throw e;
}
catch (Exception e)
{
...
}

你也可以将异常包装在另一个异常中,并通过将exception作为Throwable参数作为原因参数来保留原始的堆栈跟踪:

try
{
...
}
catch (Exception e)
{
throw new YourOwnException(e);
}
public int read(byte[] a) throws IOException {
try {
return in.read(a);
} catch (final Throwable t) {
/* can do something here, like  in=null;  */
throw t;
}
}

这是该方法抛出IOException的具体示例。final意味着t只能保存try块抛出的异常。额外的阅读材料可以找到在这里在这里

如果将捕获的异常包装到其他异常中(以提供更多信息),或者只是重新抛出捕获的异常,则会保留堆栈跟踪。

< p > <代码>{试 ... }catch (FooException e){ throw new BarException("Some useful info", e); 代码}< / > < / p >

我只是有一个类似的情况,我的代码可能会抛出一些不同的异常,我只是想重新抛出。上面描述的解决方案不适合我,因为Eclipse告诉我throw e;会导致一个未处理的异常,所以我这样做了:

try
{
...
} catch (NoSuchMethodException | SecurityException | IllegalAccessException e) {
throw new RuntimeException(e.getClass().getName() + ": " + e.getMessage() + "\n" + e.getStackTrace().toString());
}

为我工作....:)