Всегда ли выполняется блок finally в Java?
Тема: Выполнение блока finally
в Java
У меня возник вопрос по поводу выполнения блока finally
в следующем коде:
try {
something();
return success;
}
catch (Exception e) {
return failure;
}
finally {
System.out.println("Не знаю, будет ли это выведено на экран");
}
Могу ли я быть абсолютно уверенным, что блок finally
всегда будет выполнен независимо от результата выполнения метода something()
? Даже если в процессе выполнения something()
произойдет необработанное исключение или произойдет вызов System.exit()
? Спасибо за помощь!
4 ответ(ов)
Да, блок finally
будет вызван после выполнения блоков try
или catch
.
Единственные случаи, когда finally
не будет вызван:
- Если вы вызываете
System.exit()
- Если вы вызываете
Runtime.getRuntime().halt(exitStatus)
- Если виртуальная машина Java (JVM) аварийно завершает работу
- Если JVM застревает в бесконечном цикле (или в каком-либо другом не прерываемом, не завершающем выражении) в блоке
try
илиcatch
- Если операционная система принудительно завершает процесс JVM; например, команда
kill -9 <pid>
в UNIX - Если хост-система выходит из строя; например, отключение питания, ошибка оборудования, паника ОС и т. д.
- Если блок
finally
должен быть выполнен потоками-демонами, и все остальные недемоны завершили свою работу до вызоваfinally
В приведенном вами коде, метод test()
возвращает 0, но перед этим выполняется блок finally
, который печатает сообщение "something is printed".
Вот краткое пояснение:
- Основной метод (
main
): вызывает методtest()
и выводит его результат на экран. - Метод
test()
:- Внутри метода есть блок
try
, который возвращает значение 0. - Однако, перед тем как фактически завершить выполнение метода и вернуть значение, Java всегда выполняет блок
finally
(если он присутствует). - В данном случае, в блоке
finally
выполняется вывод сообщения в консоль, после чего возвращается значение 0.
- Внутри метода есть блок
Таким образом, в выводе сначала будет напечатано сообщение из блока finally
, а затем возвращаемое значение.
Поскольку блок finally
выполняется всегда, вы получите следующий вывод:
something is printed
0
Обратите внимание, что если в блоке try
или finally
возникает исключение, то оно может изменить поведение. Тем не менее, в вашем коде исключений нет, и всё работает именно так, как описано.
В дополнение к этому, хотя это и считается плохой практикой, если внутри блока finally
есть оператор return
, он переопределит любой return
, выполненный в блоке try
. То есть следующий код вернёт false
:
try { return true; } finally { return false; }
То же самое касается выбрасывания исключений из блока finally
.
Я попробовал приведенный выше пример с небольшими изменениями:
public static void main(final String[] args) {
System.out.println(test());
}
public static int test() {
int i = 0;
try {
i = 2;
return i;
} finally {
i = 12;
System.out.println("finally trumps return.");
}
}
Этот код выводит:
finally trumps return.
2
Это происходит потому, что когда выполняется return i;
, переменная i
имеет значение 2. После этого выполняется блок finally
, где переменной i
присваивается значение 12, и затем выполняется System.out.println
.
После завершения выполнения блока finally
блок try
возвращает 2, а не 12, потому что этот оператор return
больше не выполняется повторно.
Если вы отладите этот код в Eclipse, вам может показаться, что после выполнения System.out
из блока finally
снова выполняется оператор return
из блока try
. Но это не так. На самом деле возвращается значение 2.
Инициализация ArrayList в одну строчку
Что значит "Не удалось найти или загрузить основной класс"?
Как установить Java 8 на Mac
Почему в RecyclerView отсутствует onItemClickListener()?
Что значит 'synchronized'?