исключение потери в блоке catch - PullRequest
6 голосов
/ 17 октября 2010

Я запускаю этот код:

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");
        }

    }
}

Результат:
try: 1
catch: 2
finally: 3
Исключение в потоке "main" java.lang.NullPointerException в user.main (User.java:17)

в перехвате блока - ArrayIndexOutOfBoundsException, но мы теряем это исключение, почему?

Ответы [ 3 ]

7 голосов
/ 17 октября 2010

из 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 (будет интегрирован в 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 заметил и пожаловался на нулевую разыменование. Мораль истории? Запустите PMD и FindBugs!

Относящиеся

Относится к SO: Исключение глотания, выдаваемое в catch / finally . Можно ли избежать такой громоздкой попытки / поймать / наконец ...

3 голосов
/ 17 октября 2010

Вы только что наткнулись на странную особенность Java, что, если блок finally не завершается должным образом, он скрывает любые исключения, которые были выброшены ранее.

Это сделано намеренно, это не ошибка.

1 голос
/ 17 октября 2010

Последнее исключение не встречается внутри блока try { } catch { }, поэтому обработка catch { } или finally { } не выполняется.

...