6

我运行这段代码:

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
线程“main”中的异常 java.lang.NullPointerException 在 user.main(User.java:17)

在块中捕获 - ArrayIndexOutOfBoundsException,但是我们丢失了这个异常,为什么?

4

3 回答 3

7

来自 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//块catchfinally嵌套在finally块内的情况下,对此进行推理的困难是项目 COIN 中“使用资源尝试”功能的部分原因(很快将集成到 Java 中) "),您可以在此处阅读更多信息

这是花时间运行像PMD这样的静态分析器的众多充分理由之一,它发现并抱怨这种类型的混乱——尽管它可能无法在您的代码中捕捉到这种情况,但我不确定。

静态检查

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

finally { throw NullPointerException("Foo"); }

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

对于前者,PMD 注意到并抱怨从finally子句抛出异常。FindBugs 一点也不抱怨。对于后者,PMD 抱怨了几件事,但没有任何关联(“LocalVariableCouldBeFinal”、“StringToString”和“UselessOperationOnImmutable”)。然而,FindBugs 注意到并抱怨了 null 取消引用。故事的道德启示?同时运行 PMD 和 FindBugs!

有关的

与 SO 相关:在 catch/finally 中引发的吞咽异常我能避免这样繁琐的try/catch/finally...

于 2010-10-17T19:01:24.427 回答
3

您刚刚偶然发现了 Java 的一个奇怪特性,即如果 finally 块没有正确终止,它会隐藏之前抛出的所有异常。

这是设计使然,不是错误。

于 2010-10-17T18:36:52.710 回答
1

您最后一个异常不会发生在try { } catch { }块内,因此没有catch { }或正在finally { }处理。

于 2010-10-17T18:37:30.907 回答