Всегда ли выполняется блок finally в Java? - PullRequest
2172 голосов
/ 15 сентября 2008

Учитывая этот код, могу ли я быть абсолютно уверенным , что блок finally всегда выполняется, независимо от того, чем является something()?

try {  
    something();  
    return success;  
}  
catch (Exception e) {   
    return failure;  
}  
finally {  
    System.out.println("I don't know if this will get printed out");
}

Ответы [ 46 ]

5 голосов
/ 02 апреля 2018

Да, здесь написано здесь

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

5 голосов
/ 09 ноября 2017

Блок finally не будет вызываться после возврата в паре уникальных сценариев: если сначала вызывается System.exit () или происходит сбой JVM.

Позвольте мне попытаться ответить на ваш вопрос как можно проще.

Правило 1 : блок finally всегда выполняется (Хотя есть исключения из этого. Но давайте придерживаться этого некоторое время.)

Правило 2 : операторы в блоке finally запускаются, когда управление покидает блок try или catch. Передача управления может происходить в результате нормального выполнения, выполнения break, continue, goto или заявление о возврате, или о распространении исключения.

В случае с оператором return, в частности (с его заголовком), элемент управления должен покинуть вызывающий метод, и, следовательно, вызвать блок finally соответствующей структуры try-finally. Оператор return выполняется после блока finally.

Если в блоке finally также есть оператор возврата, он обязательно переопределит ожидающий в блоке try, поскольку он очищает стек вызовов.

Лучшее объяснение вы можете найти здесь: http://msdn.microsoft.com/en-us/.... концепция в основном одинакова на всех языках высокого уровня.

5 голосов
/ 20 мая 2017
  1. Наконец, Блок всегда выполняется. Если и до System.exit () оператор существует там (первый оператор в блоке finally).
  2. Если system.exit () является первым оператором, то блок finally не будет выполнен, и управление выйдет из блока finally. Всякий раз, когда оператор System.exit () попадает в блок finally, пока этот оператор не завершит выполнение блока, а когда появится System.exit (), управляющая сила полностью выйдет из блока finally.
5 голосов
/ 12 декабря 2015

НЕ ВСЕГДА

Спецификация языка Java описывает, как блоки try-catch-finally и try-catch работают на 14.20.2
Ни в каком месте это не указывает, что блок finally всегда выполняется. Но для всех случаев, когда блоки try-catch-finally и try-finally завершаются, он указывает, что перед выполнением, наконец, должен быть выполнен finally.

try {
  CODE inside the try block
}
finally {
  FIN code inside finally block
}
NEXT code executed after the try-finally block (may be in a different method).

JLS не гарантирует, что FIN будет выполнено после CODE . JLS гарантирует, что если CODE и NEXT будут выполнены, то FIN всегда будет выполняться после CODE и до NEXT .

Почему JLS не гарантирует, что блок finally всегда выполняется после блока try? Потому что это невозможно. Маловероятно, но возможно, что JVM будет прервана (kill, crash, power off) сразу после завершения блока try, но перед выполнением блока finally. JLS ничего не может сделать, чтобы этого избежать.

Таким образом, любое программное обеспечение, для которого его правильное поведение зависит от блоков finally, всегда выполняющихся после завершения их блоков try.

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

5 голосов
/ 01 октября 2008

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

4 голосов
/ 13 сентября 2016

Да, он всегда будет вызываться, но в одной ситуации он не будет вызываться при использовании System.exit ()

try{
//risky code
}catch(Exception e){
//exception handling code
}
finally(){
//It always execute but before this block if there is any statement like System.exit(0); then this block not execute.
}
4 голосов
/ 17 февраля 2014

Наконец, блок всегда выполняется независимо от того, обрабатывается ли исключение. Если какое-либо исключение возникло до блока try, то, наконец, блок не будет выполнен.

4 голосов
/ 04 июля 2016

То же самое со следующим кодом:

static int f() {
    while (true) {
        try {
            return 1;
        } finally {
            break;
        }
    }
    return 2;
}

f вернет 2!

4 голосов
/ 17 апреля 2012

Попробуйте этот код, вы поймете, что код в блоке finally выполняется после оператора возврата .

public class TestTryCatchFinally {
    static int x = 0;

    public static void main(String[] args){
        System.out.println(f1() );
        System.out.println(f2() );
    }

    public static int f1(){
        try{
            x = 1;
            return x;
        }finally{
            x = 2;
        }
    }

    public static int f2(){
        return x;
    }
}
4 голосов
/ 13 мая 2010

Рассмотрим это в обычном порядке выполнения (т. Е. Без каких-либо исключений): если метод не 'void', то он всегда явно что-то возвращает, но, наконец, всегда выполняется

...