块捕获中的丢失exception

我运行这段代码:

public class User { public static void main(String args[]) { int array[] = new int[10]; int i = 1; try { System.out.println("try: " + i++); System.out.println(array[10]); System.out.println("try"); } catch (Exception e) { System.out.println("catch: " + i++); System.out.println(array[10]); System.out.println("catch"); } finally { System.out.println("finally: " + i++); Object o = null; o.hashCode(); System.out.println("finally"); } } } 

结果:
尝试:1
捕获:2
最后:3
user.main中线程“main”java.lang.NullPointerException中的exception(User.java:17)

在block catch中 – ArrayIndexOutOfBoundsException,但是我们丢失了这个Exception,为什么呢?

来自JLS

您可以在JLS, 块和语句的 “14.19.2 try-catch-finally的执行”部分中阅读此内容。 我引用了,

如果try块的执行由于任何其他原因R突然完成,则执行finally块。 然后有一个选择:

  • 如果finally块正常完成,则try语句突然完成,原因是R.
  • 如果finally块因为原因S而突然完成,则try语句突然完成,原因是S(并且原因R被丢弃)。 这个例子…

因此,以下(从提问者的代码中真正浓缩)完成了NPE,而不是ExceptionTest抛出。

 class Phinally { static class ExceptionTest extends Exception { public ExceptionTest(String message) { super(message); } } public static void main(String[] args) throws ExceptionTest { try { System.out.println("Foo."); throw new ExceptionTest("throw from try"); } finally { throw new NullPointerException("throw from finally"); } } } 

关于try使用资源/ ARM块的侧边栏

在一些常见情况下,特别是在管理资源,需要嵌套的try / catch / finally块以及嵌套在finally块中的常见情况下,这是一个难点,这是项目COIN中“尝试使用资源”function的原因之一(要集成到Java“相当快”),您可以在这里阅读更多相关信息 。

这是投入时间运行像PMD这样的静态分析器的众多好理由之一,它发现并抱怨这种类型的混淆 – 虽然它可能无法捕捉到你的代码中的情况,但我不确定。

静态检查

跟进@stacktrace的评论:我通过PMD和FindBugs运行相关代码,尝试以下两种方法:

 finally { throw NullPointerException("Foo"); } 

 finally { Object o = null; System.out.println(o.toString()); } 

对于前者,PMD注意到并抱怨从finally子句抛出exception。 FindBugs根本没有抱怨。 对于后者,PMD抱怨了几件事但没有任何关系(“LocalVariableCouldBeFinal”,“StringToString”和“UselessOperationOnImmutable”)。 然而,FindBugs注意到并且抱怨了一个空取消引用。 故事的道德启示? 运行PMD和FindBugs!

有关

与SO相关: 在catch / finally中抛出吞咽exception 。 我可以避免这种繁琐的尝试/捕获/最终……

您刚刚偶然发现了Java的一个奇怪特性,如果finally块没有正确终止,它会隐藏先前抛出的任何exception。

这是设计,这不是一个错误。

最后一个exception不会发生在try { } catch { }块中,因此没有catch { }finally { }处理。