在不丢失堆栈跟踪的情况下重新使用Java中的异常

rip*_*234 397 java exception

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

try
{
   ...
}
catch (Exception e)
{
   if (e is FooException)
     throw;
}
Run Code Online (Sandbox Code Playgroud)

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

Bri*_*new 536

catch (WhateverException e) {
    throw e;
}
Run Code Online (Sandbox Code Playgroud)

将简单地重新抛出你捕获的异常(显然,周围的方法必须通过其签名等来允许).该异常将保持原始堆栈跟踪.

  • @James如果你抓住(例外e){throw e; 那将是未经处理的.如果你'抓住(InterruptedException ie){throw ie; 它将被处理.根据经验,不要"抓住(例外e)" - 这不是口袋妖怪,我们不想抓住它们! (179认同)
  • 嗨,InterruptedException e在我添加throw e行时给出一个未处理的Exception消息.如果我用更广泛的Exception e替换它,那不是这样.该如何正确完成? (4认同)
  • 在Java 7中,这种重新抛出的编译器更加智能.现在它在包含方法的特定"抛出"异常中工作正常. (2认同)
  • @corsiKa不一定要“全部抓住”,这只是一个不同的用例。如果您有一个顶级循环或事件处理程序(例如,在线程的运行中),但至少没有捕获RuntimeException并将其记录下来,则您通常会完全错过该异常,并且在重要的循环中默默地中断通常是一次失败。对于不知道其他代码可能起作用或引发的插件功能,这也确实非常有用。对于像这样的自上而下的使用,捕获异常通常不仅是一个好主意,而且是一种最佳实践。 (2认同)
  • @CorsiKa 我提到它是因为我工作的应用程序有几个线程随机吃异常。任何您不想悄悄退出的线程都应该在顶部有一个 catch Exception,并且您可能要考虑到有很多开发人员并不处于您的确切情况——许多程序员使用线程,并非所有人都使用框架来抽象它们——有些人编写自己的框架。 (2认同)

Mar*_*erg 81

我会比较喜欢:

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

  • @Stroboskop:是的,但要回答它最好使用与问题中相同(相似)的代码! (19认同)
  • 有时捕获所有异常是可以的.比如在你写一个测试用例的时候.或者用于记录目的.或者在主要的地方没有捕获意味着崩溃. (13认同)
  • -1因为除非你知道自己在做什么,否则你永远不应该抓住"异常". (8认同)
  • 在Java中绝对适当地捕获特定的异常,而不是泛型和检查实例.+1 (5认同)
  • 此模式适用于RuntimeExceptions. (2认同)
  • @JohnHenckel 和其他人:有效点已确定。我更新了问题,以明确指出在大多数(但不是全部)情况下,捕获“Exception”通常不是正确的做法。 (2认同)

Olv*_*gor 71

您还可以将异常包装在另一个异常中并通过将Exception作为Throwable作为cause参数传递来保留原始堆栈跟踪:

try
{
   ...
}
catch (Exception e)
{
     throw new YourOwnException(e);
}
Run Code Online (Sandbox Code Playgroud)

  • 我还建议在旁边添加一条消息,使用`throw new YourOwnException("尝试......时出错",e); (7认同)
  • 这正确显示了错误消息,但堆栈跟踪将错误行显示为带有“throw new.......(e)”的行,而不是导致异常的原始行。 (4认同)

alv*_*ves 22

在Java中几乎是一样的:

try
{
   ...
}
catch (Exception e)
{
   if (e instanceof FooException)
     throw e;
}
Run Code Online (Sandbox Code Playgroud)

  • 我会为FooException添加一个特定的catch (28认同)
  • 不,只要您不实例化新的Exception对象,堆栈跟踪就会保持不变. (5认同)
  • 在这个特定的情况下,我同意,但添加一个特定的catch可能不是正确的选择 - 想象你有一些所有异常的公共代码,然后,对于特殊的例外,重新抛出它. (3认同)
  • 是的,但这不是问题。 (2认同)

Dav*_*d M 13

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


Sin*_*dre 7

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

try{ ... }catch (FooException e){ throw new BarException("Some usefull info", e); }


小智 6

这样的事情

try 
{
  ...
}
catch (FooException e) 
{
  throw e;
}
catch (Exception e)
{
  ...
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*iel 5

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是方法抛出的具体示例IOException.该final方法t只能保存try块抛出的异常.其他阅读材料可以在这里这里找到.

  • 它不必是最终的。请参阅 http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html 和 http://stackoverflow.com/a/6889301/131160 (2认同)