Почему, наконец, выводится трассировка стека исключения?

#java #exception #stack-trace

Вопрос:

Вот мой простой тестовый код:

 class Scratch {
    public static void main(String[] args) {
        try {
            System.out.println("Line 1");
            throw new RuntimeException();
        } catch (RuntimeException e) {
            e.printStackTrace();
        } finally {
            System.out.println("Line 2");
        }
    }
}
 

После пробежки я получу это:

 Line 1
Line 2
java.lang.RuntimeException
    at Scratch.main(scratch_4.java:5)

Process finished with exit code 0
 

Я думал, что «наконец-то» код должен быть наконец-то выполнен, но это не так.
В чем причина?

Комментарии:

1. Я думаю, что, наконец, просто определено, что он должен выполняться до ввода кода catch . Я должен был бы посмотреть это в спецификации языка, хотя, чтобы быть уверенным.

2. @markspace: Нет, он определенно выполняется после блока catch.

3. Я принимаю поправку! Я оставлю свой комментарий, хотя, поскольку я думаю, что это иллюстрирует возможное недоразумение.

4. @markspace Я собирался сказать, что ключевое finally слово должно дать понять, что это последнее, что должно произойти; но затем я заметил, что в руководстве по Oracle говорится : «Блок finally всегда выполняется при выходе блока try»., что является довольно вводящим в заблуждение утверждением. Как говорит ДжоНскит: он определенно выполняется после перехвата, если при попытке было создано соответствующее исключение.

Ответ №1:

По умолчанию printStackTrace печатается на System.err , в то время как вы пишете на System.out . Таким образом, вы пишете в два разных потока, и в вашем конкретном случае похоже, что задействованная буферизация изменила порядок вывода из фактического порядка выполнения.

Если вы либо пишете в один поток (например, используя System.err.println или вызывая e.printStackTrace(System.out) ), либо измените свой catch блок, чтобы просто писать System.out , как это делают другие ваши строки, вы увидите порядок try => catch =>> наконец.