Учитывая этот код, могу ли я быть абсолютно уверен, что 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");
}
java
error-handling
return
try-catch-finally
Джонни пять
источник
источник
probably
вместо.finally
; финализатор ==finalize()
метод.Ответы:
Да,
finally
будет вызываться после выполнения блоков кодаtry
илиcatch
.Единственные времена
finally
не будут называться:System.exit()
Runtime.getRuntime().halt(exitStatus)
try
orcatch
kill -9 <pid>
в UNIXfinally
блок будет выполняться потоком демона и все другие потоки, не являющиеся демонами, завершатся доfinally
вызоваисточник
thread.stop()
не обязательно препятствует выполнениюfinally
блока.finally
блок будет называться после того, как вtry
блоке, и перед тем управление переходит к следующим заявлениям. Это согласуется с блоком try, включающим бесконечный цикл и, следовательно, блок finally, который фактически никогда не вызывается.Пример кода:
Вывод:
источник
finally
-clausereturn 2;
недопустима (ошибка компилятора).Кроме того, хотя это и плохая практика, если в блоке finally есть оператор return, он превзойдет любой другой возврат из обычного блока. То есть следующий блок вернул бы false:
То же самое с выбрасыванием исключений из блока finally.
источник
Вот официальные слова из спецификации языка Java.
14.20.2. Выполнение try-finally и try-catch-finally
Спецификация для
return
фактически делает это явным:JLS 14.17 Заявление о возврате
источник
В дополнение к другим ответам важно указать, что 'finally' имеет право переопределить любое исключение / возвращаемое значение с помощью блока try..catch. Например, следующий код возвращает 12:
Точно так же следующий метод не вызывает исключение:
В то время как следующий метод бросает это:
источник
OutOfMemoryError
? ;)return retVal
после того, как вfinally
блоке, хотя это, конечно , предполагает , что вы подавляются некоторые другие исключения , потому что код не имеет смысла иначе.Я попробовал приведенный выше пример с небольшой модификацией
Вышеприведенный код выводит:
Это потому, что когда
return i;
выполняется,i
имеет значение 2. После этого выполняетсяfinally
блок, где назначается 12,i
а затемSystem.out
выполняется out.После выполнения
finally
блокаtry
блок возвращает 2, а не 12, потому что этот оператор возврата больше не выполняется.Если вы будете отлаживать этот код в Eclipse , то вы получите ощущение , что после выполнения
System.out
изfinally
блока наreturn
заявленииtry
блока выполняются снова. Но это не так. Он просто возвращает значение 2.источник
i
был не примитив, а объект Integer.Вот разработка ответа Кевина . Важно знать, что возвращаемое выражение вычисляется раньше
finally
, даже если оно возвращается после.Вывод:
источник
finally
. Вычисление возвращаемого значения (printX()
здесь) по-прежнему предшествует ему.System.out.println("finally trumps return... sort of");
наSystem.out.print("finally trumps return in try"); return 42;
Вот и вся идея окончательного блока. Это позволяет вам убедиться, что вы делаете очистки, которые в противном случае могли бы быть пропущены, потому что вы возвращаетесь, среди прочего, конечно.
Наконец вызывается независимо от того, что происходит вызывается в блоке try ( если только вы не вызываете
System.exit(int)
или не виртуальная машина Java по какой-то другой причине).источник
Логичный способ думать об этом:
источник
Наконец, всегда выполняется finally, если нет ненормального завершения программы (например, вызов System.exit (0) ..). Итак, ваш системный будет напечатан
источник
Также возврат в, наконец, отбросит любое исключение. http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
источник
Блок finally всегда выполняется, если не происходит аварийного завершения программы, вызванного сбоем JVM или вызовом
System.exit(0)
.Кроме того, любое значение, возвращаемое из блока finally, будет переопределять значение, возвращаемое до выполнения блока finally, поэтому будьте осторожны при проверке всех точек выхода при использовании try finally.
источник
Нет, не всегда одним случаем исключения является // System.exit (0); прежде чем блок finally не позволяет выполнить, наконец, finally.
источник
Наконец, всегда запускается, и в этом весь смысл, просто потому, что он появляется в коде после возврата, не означает, что так оно и реализовано. Среда выполнения Java отвечает за запуск этого кода при выходе из
try
блока.Например, если у вас есть следующее:
Среда выполнения сгенерирует что-то вроде этого:
Если генерируется неперехваченное исключение,
finally
блок будет запущен, и исключение продолжит распространяться.источник
Это потому, что вы присвоили значение i как 12, но не вернули значение i в функцию. Правильный код выглядит следующим образом:
источник
Потому что блок finally всегда будет вызываться, пока вы не вызовете
System.exit()
(или поток не завершится).источник
Вкратце, в официальной документации Java (Нажмите здесь ) написано, что -
источник
ВХОД:
ВЫВОД:
источник
Да, это будет называться. Вот и весь смысл иметь ключевое слово finally. Если выпрыгивание из блока try / catch может просто пропустить блок finally, это то же самое, что поместить System.out.println вне try / catch.
источник
Да, наконец, блок всегда выполняется. Большинство разработчиков используют этот блок для закрытия соединения с базой данных, объекта набора результатов, объекта оператора, а также использует в спящем режиме Java для отката транзакции.
источник
НЕ ВСЕГДА
Спецификация языка Java описывает, как
try
-catch
-finally
иtry
-catch
блоки работают в 14.20.2В каком месте он указывает , что
finally
блок всегда выполняется. Но во всех случаях , в которыхtry
-catch
-finally
иtry
-finally
блоки заполнить это указать , что до завершенияfinally
должно быть выполнено.JLS не гарантирует, что FIN выполняется после CODE . JLS гарантирует, что если выполняются CODE и NEXT , то FIN всегда будет выполняться после CODE и до NEXT .
Почему JLS не гарантирует, что
finally
блок всегда выполняется послеtry
блока? Потому что это невозможно. Маловероятно, но возможно, что JVM будет прервана (kill, crash, power off) сразу после завершенияtry
блока, но перед выполнениемfinally
. JLS ничего не может сделать, чтобы избежать этого.Таким образом, любое программное обеспечение, для которого его правильное поведение зависит от
finally
блоков, всегда выполняющихся после того, как ихtry
блоки завершены, прослушиваются.return
инструкции вtry
блоке не имеют отношения к этой проблеме. Если выполнение достигает кода послеtry
-catch
-finally
гарантируется, чтоfinally
блок будет выполнен до, сreturn
инструкциями внутриtry
блока или без него .источник
Да, это будет. Независимо от того, что происходит в вашем блоке try или catch, если не вызывается System.exit () или не происходит сбой JVM. если есть какой-либо оператор возврата в блоке (ах), то, наконец, будет выполнен до этого оператора возврата.
источник
Да, это будет. Единственный случай, когда это не будет, JVM выходит или вылетает
источник
Добавление к ответу @ vibhash, поскольку никакой другой ответ не объясняет, что происходит в случае изменяемого объекта, подобного приведенному ниже.
Будет выходной
источник
Я попробовал это, это однопоточный.
main
Thread
Будет наwait
состоянии навсегда, следовательно ,finally
никогда не будет называться ,поэтому вывод на консоль не будет
print
String
: послеwait()
илиfinally
Согласен с @Stephen C, приведенный выше пример является одним из 3-х упоминаний здесь :
Добавим еще несколько таких возможностей бесконечного цикла в следующем коде:
Случай 2: если JVM падает первым
Ссылка: как вы разбили JVM?
Случай 6: если
finally
блок будет выполняться демономThread
и все другие не-демонныеThreads
выходы до того, какfinally
будет вызван.выходные данные: это не выводит «finally», что означает, что «блок finally» в «потоке демона» не был выполнен
источник
Рассмотрим следующую программу:
Начиная с Java 1.8.162, приведенный выше блок кода дает следующий вывод:
это означает, что использование
finally
для освобождения объектов является хорошей практикой, такой как следующий код:источник
sb.setLength(0)
в конце концов?sb = null;
просто добавляет ненужный код. Я понимаю, что вы имеете в виду, чтоfinally
блок - это хорошее место для освобождения ресурсов, таких как соединение с базой данных или что-то подобное, но имейте в виду, что ваш пример может запутать новичков.System.out.println("---AGAIN2---");
System.out.println(sb);
и теперь это стало понятнее. Как бы то ни было, результат был против вашего тезиса: p Я также добавил к вашему ответу, но редактирование должно быть принято модератором или кем-то вроде этого.Это действительно так в любом языке ... finally всегда будет выполняться перед оператором return, независимо от того, где этот возврат находится в теле метода. Если бы это было не так, блок finally не имел бы большого значения.
источник
В дополнение к пункту о возврате в окончательной замене возврата в блоке try, то же самое относится и к исключению. Блок finally, который генерирует исключение, заменит возврат или исключение, выброшенное из блока try.
источник
finally
выполнит и это точно.finally
не будет выполняться в следующих случаях:Дело 1 :
Когда вы выполняете
System.exit()
.случай 2:
Когда ваша JVM / Thread падает.
случай 3:
Когда ваше выполнение остановлено между вручную.
источник
источник