Rethrowing exceptions in Java without losing the stack trace
在C_中,我可以使用throw;语句在保留堆栈跟踪的同时重新引发异常:
1 2 3 4 5 6 7 8 9
| try
{
...
}
catch (Exception e )
{
if (e is FooException )
throw;
} |
Java中有类似的东西(不会丢失原始堆栈跟踪)吗?
- 为什么你认为它会松开原来的stacktrace?当抛出新的someOtherException并忘记在构造函数或initcuse()中分配根本原因时,释放它的唯一方法。
- 我相信这就是代码在.NET中的行为方式,但我不再乐观。也许值得在某个地方查找它或者运行一个小测试。
- Throwable不会通过抛出它们来修改。要更新堆栈跟踪,必须调用fillInStackTrace()。方便地在EDOCX1的构造函数(0)中调用此方法。
- 在C中,是的,throw e;将丢失stacktrace。但不是在Java中。
- Oracle的一些doc关于Java 7的异常:捕获多个异常类型并使用改进类型检查重新抛出异常
1 2 3
| catch (WhateverException e) {
throw e;
} |
只需重新引发捕获到的异常(显然,周围的方法必须通过其签名等允许这样做)。异常将保留原始堆栈跟踪。
- 嗨,InterruptedException E在添加throw E行时会给出未处理的异常消息。不是这样的,如果我用更广泛的例外来代替它,这应该怎么做呢?
- @james,我刚刚注意到,如果在函数声明中添加"throws xxxexception",消息就会消失。
- 在Java 7编译器中,这样的重排更为智能化。现在它可以在包含方法中处理特定的"throw"异常。
- @詹姆斯,如果你是1号[0号],那就不需要处理了。如果你同意,我们会处理的。作为经验法则,不要以东克星(2)-这不是口袋妖怪,我们不想抓住他们!
- 在我正在研究的Java项目中,我看到了一些类似的代码——它是一个NOP操作,安全删除吗?
- @如果这是Try with Resources语句,则不应删除它。
- @Corsika不一定是真的你不想"抓住他们",这只是一个不同的用例。如果您有一个顶级的循环或事件处理程序(例如,在线程的运行中),如果您没有捕捉到至少一个run time exception并将其记录下来,那么您通常会完全错过这个异常,并且会因为通常是一次性失败而悄悄地从一个重要的循环中脱离出来。它对于插件功能也很好,因为您不知道其他代码可能会做什么或抛出什么…对于这些自上而下的用法,捕获异常通常不仅是一个好主意,而且是一个最佳实践。
- @当然可以。但这个顶级循环通常是由一个高级框架来处理的。您的典型开发人员很少在这种级别上进行编写,如果是,他们知道什么时候需要忽略拇指规则。
- @我之所以提到它,是因为我开发的应用程序有几个线程随机接受异常。任何你不想悄悄跳出的线程都应该在顶部有一个catch异常,你可能会认为有很多开发人员不在你的确切情况下——许多程序员使用线程,而不是所有的开发人员都使用框架来抽象线程——还有一些人编写自己的框架。
- @CORSIKA-我可以这样做吗?捕获不同类型的IOException(例如,fileNotFoundException),然后在用消息将其包装在IOException对象中后,重新对其进行处理?我在这里问了一个相关的问题。希望你能帮忙-stackoverflow.com/questions/47646945/…
- 我认为值得一提的是,对于学习Java的人来说,周围的方法必须允许重新抛出异常可能不是"显而易见"的。surroundingMethod() throws WhateverException { ... }
我宁愿:
1 2 3 4 5 6 7 8 9 10 11
| try
{
...
}
catch (FooException fe ){
throw fe ;
}
catch (Exception e )
{
...
} |
- 在Java中绝对正确地捕捉特定的异常,而不是泛型和检查实例。+ 1
- 对于RuntimeExceptions,此模式工作得很好。
- 并希望fooException未选中或在封闭方法的throws部分中声明。C异常未经检查,可以自由地重新抛出。
- -1因为除非你知道自己在做什么,否则你永远不应该明白"例外"。
- @斯特罗博斯科普:是的,但要回答这个问题,最好使用与问题相同(类似)的代码!
- 在这种情况下,是的。但是,有时,只有当(自定义)异常的属性具有一些"可恢复"值时,才可以从自定义异常中恢复,因此上面的窗体很有趣。
- 有时捕获所有异常是可以的。例如,编写测试用例时。或用于日志记录。或者主要是没有抓到就意味着撞车。
您还可以将异常包装在另一个异常中,并通过将异常作为可丢弃的原因参数传入来保留原始堆栈跟踪:
1 2 3 4 5 6 7 8
| try
{
...
}
catch (Exception e )
{
throw new YourOwnException (e );
} |
- 我还建议使用throw new YourOwnException("Error while trying to ....", e);在旁边添加消息。
- 这就是我要找的,尤其是第一条评论的版本,在这里你可以传递你自己的信息。
在Java中几乎是一样的:
1 2 3 4 5 6 7 8 9
| try
{
...
}
catch (Exception e )
{
if (e instanceof FooException )
throw e ;
} |
- 不,只要不实例化新的异常对象,stacktrace就保持不变。
- 我会为fooexception添加一个特定的catch
- 在这个特定的情况下,我同意,但是添加一个特定的catch可能不是正确的选择——假设您对所有的异常都有一些通用的代码,然后,对于一个特定的异常,重新执行它。
- @Markuslausberg,但最终无法捕获异常。
- 是的,但这不是问题。
在爪哇中,您只需抛出捕获的异常,那么EDOCX1就等于0而不是EDCOX1(1)。Java维护堆栈跟踪。
1 2 3 4 5 6 7 8
| 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块抛出的异常。其他阅读材料可以在这里和这里找到。
- 这不一定是最终决定。请参阅docs.oracle.com/javase/7/docs/technotes/guides/language/…和stackoverflow.com/a/6889301/131160
像这样的东西
1 2 3 4 5 6 7 8 9 10 11 12
| try
{
...
}
catch (FooException e )
{
throw e ;
}
catch (Exception e )
{
...
} |
如果将捕获的摘录包装成另一个异常(以提供更多信息),或者只是重新引发捕获的摘录,则需要提供堆栈跟踪。
try{
...
}catch (FooException e){
throw new BarException("Some usefull info", e);
}