Подтвердить что ты не робот

Что на первом месте - или блок catch?

Рассмотрим следующий тестовый пример:

public class Main {

    static int a = 0;

    public static void main(String[] args) {
        try {
            test();
            System.out.println("---");
            test2();
        }
        catch(Exception e) {
            System.out.println(a + ": outer catch");
            a++;
        }
    }

    public static void test()
    {
        try {
            throw new Exception();
        }
        catch (Exception e) {
            System.out.println(a + ": inner catch");
            a++;
        }
        finally {
            System.out.println(a + ": finally");
            a++;
        }
    }

    public static void test2() throws Exception
    {
        try {
            throw new Exception();
        }
        finally {
            System.out.println(a + ": finally");
            a++;
        }
    }
}

С выходом:

0: inner catch
1: finally
---
2: finally
3: outer catch

Какое объяснение почему в test() catch происходит до того, пока наконец в test2() это наоборот?

4b9b3361

Ответ 1

Поскольку блок try в test2() не имеет блока catch, только a finally. Код не будет "возвращаться" к вызывающему, чтобы упасть в catch, а затем "перейти вперёд" к finally, чтобы продолжить там, как вы, кажется, думаете.

Ответ 2

Ключевые моменты:

  • В блоке try-(catch)-finally finally для этого конкретного блока try выполняется последним
  • Вы можете вложить блоки try в другой, и каждый из этих вложенных блоков try может иметь свой собственный finally, который будет выполняться последним для этих отдельных блоков try

Итак, да, finally выполняется последним, но только для блока try, к которому он привязан.

Итак, дадим следующий фрагмент:

try {
    try {
        throw null;
    } finally {
        System.out.println("Finally (inner)");
    }
} catch (Throwable e) {
    System.out.println("Catch (outer)");
}

Отпечатает (как видно на ideone.com):

Finally (inner)
Catch (outer)

Заметим, что:

  • Внутри (inner), finally является последним (независимо от того, успешно или нет catch)
  • Catch (outer) следует за Finally (inner), но потому, что Finally (inner) вложен внутри другого блока try внутри (outer)

Аналогично, следующий фрагмент:

    try {
        try {
            throw null;
        } catch (Throwable e) {
            System.out.println("Catch (inner)");
        } finally {
            System.out.println("Finally (inner)");
            throw null;
        }
    } catch (Throwable e) {
        System.out.println("Catch (outer)");
    }

Это печатает (как видно на ideone.com):

Catch (inner)
Finally (inner)
Catch (outer)

Ссылки

Связанные вопросы

Ответ 3

catch приходит, наконец, в ту же область try-catch-finally.

В test2 нет никакого catch в области try-catch-finally test2, поэтому он наконец-то покидает область и падает в более высокий улов.

Ответ 4

Поскольку блок finally всегда выполняется непосредственно перед выходом из области видимости. После событий test2() последовательность событий следующая:

  • Исключение
  • выбрано в test2()
  • Так как test2 не имеет блока catch, исключение распространяется до вызывающего.
  • Так как test2 имеет блок finally, он запускается перед возвратом из метода.
  • catch в основном методе ловит исключение.

Ответ 5

Потому что наконец - это самый последний код для выполнения в блоке try..catch, независимо от того, было ли выбрано исключение, выбрано, а затем обработано или вообще не выбрано.

Фактически единственный раз, когда будет вызван не, является то, что JVM завершает работу до того, как он его выполнит, или если поток, выполняющий код try, был убит или прерван.

В ответ на комментарии: Java Описание окончательно

Note: If the JVM exits while the try or catch code is being executed,

тогда блок finally может не выполнить. Аналогично, если поток выполнение кода try или catch прерван или убит, наконец блок может не выполняться, даже если приложение в целом продолжается.

Однако вы правы, что вызывается исключение ThreadDeath, и я не могу много узнать о специфике того, что кажется противоречивой информацией от солнца. Это может быть вопрос сам по себе.

наконец (простите за каламбур) @brainimus, если вы в конце, и вы выбрали исключение, тогда выполняется код finally , моя точка была условия, при которых код finally не выполняется.

Ответ 6

try-catch и, наконец, используются для предотвращения ситуаций, когда программа может быть прекращена из-за возникновения нежелательной ошибки во время выполнения программы.

Важны важные моменты...

1) Существует только одна попытка для блока...... любое количество операторов catch для блока и только один для блока статусов

2), наконец, является необязательным.

3) catch также является необязательным, но если инструкция catch отсутствует, то, наконец, должна появиться.

4) Все уловы, соответствующие дочерним исключениям, должны появляться перед уловом для родительского исключения.

5) Независимо от присутствия исключения, операторы, присутствующие в блоке finally, выполняются всегда с одним исключением.

то есть. Если встречается оператор System.out.exit(), то программа немедленно прекращается, поэтому в таких случаях невозможно выполнить.

Примечание: даже в операторе try появляется оператор return... тогда также выполняется код в.

Ответ 7

Если вы замените функции кодом методов, вы получите:

public class Main {

    static int a = 0;

    public static void main(String[] args) {
        try {
            try {
                throw new Exception();
            }
            catch (Exception e) {
                // I catch only the *first* exception thrown   
                System.out.println(a + ": inner catch");
                a++;
                // let go to the finally block
            }
            finally {
                System.out.println(a + ": finally");
                a++;
                // we go on
            }
            System.out.println("---");
            try {
                throw new Exception();
            }
            finally {
                // executed because at the same level
                System.out.println(a + ": finally");
                a++;
            }
        }
        catch(Exception e) {
            // I catch only the *second* exception thrown
            System.out.println(a + ": outer catch");
            a++;
        }
    }

Первое исключение делает блок catch выполненным, тогда выполняется первый блок finally. Это не видно на внешнем уровне из-за первого блока catch. Второе исключение перехватывается блоком catch на внешнем уровне, но сначала выполняется первое, находящееся на внутреннем уровне.

Ответ 8

Сначала запускается блок try. Catch выполняется, если в блоке try есть исключение, которое необходимо поймать. Наконец, блок запускается в обоих случаях, есть ли исключение или нет. Если в блоке try есть ответ, то перед возвратом в блок try, блок finally выполняется, а затем возврат выполняется в блоке try.