Вопрос-ответ

Does a finally block always get executed in Java?

Всегда ли блок finally выполняется в Java?

Учитывая этот код, могу ли я быть абсолютно уверен, что 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");
}
Переведено автоматически
Ответ 1

Да, finally будет вызван после выполнения блоков кода try или catch.

Единственные случаи, когда finally не будет вызван, это:


  1. Если вы вызовете System.exit()

  2. Если вы вызовете Runtime.getRuntime().halt(exitStatus)

  3. Если JVM выходит из строя первой

  4. Если JVM достигает бесконечного цикла (или какого-либо другого не прерываемого, не завершающего оператора) в блоке try or catch

  5. Если ОС принудительно завершает процесс JVM; например, kill -9 <pid> в UNIX

  6. Если хост-система умирает; например, сбой питания, аппаратная ошибка, сбой операционной системы и так далее

  7. Если finally блок будет выполняться потоком демона, а все другие потоки, не являющиеся демонами, завершаются до finally вызова

Ответ 2

Пример кода:

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

public static int test() {
try {
return 0;
}
finally {
System.out.println("something is printed");
}
}

Вывод:

something is printed. 
0
Ответ 3

Кроме того, хотя это плохая практика, если в блоке finally есть оператор return , он превзойдет любой другой возврат из обычного блока. То есть следующий блок вернет false:

try { return true; } finally { return false; }

То же самое с выбрасыванием исключений из блока finally .

Ответ 4

Вот официальные слова из спецификации языка Java.

14.20.2. Выполнение try-finally и try-catch-finally


try Инструкция с finally блоком выполняется путем первого выполнения try блока. Затем есть выбор:



  • Если выполнение try блока завершается нормально, [...]

  • Если выполнение try блока внезапно завершается из-за throw значения V, [...]

  • Если выполнение try блока внезапно завершается по какой-либо другой причине R, то finally блок выполняется. Тогда есть выбор:

    • Если блок finally завершается нормально, то try оператор завершается внезапно по причине R.

    • Если finally блок завершается внезапно по причине S, то try оператор завершается внезапно по причине S (и причина R отбрасывается).



Спецификация для return на самом деле делает это явным:

JLS 14.17 Оператор return


ReturnStatement:
return Expression(opt) ;

return Оператор без Expression попыток передать управление вызывающему методу или конструктору, который его содержит.


return Оператор с an Expression пытается передать управление вызывающему методу, который его содержит; значение Expression становится значением вызова метода.


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


java