возврат блока try/catch с предложением finally в java

Учитывая следующий блок try/catch в java:

try{
  return;
}
catch(SomeException e){
  System.out.println(e);
}
finally{
  System.out.println("This is the finally block");
}

и согласно этому сообщению: "Всегда ли наконец выполняется в Java?" Я можно увидеть, что вывод программы будет «Это блок finally». Однако я не могу понять, как это возможно, поскольку оператору печати предшествует return...

Я подозреваю, что это поведение имеет какое-то отношение к многопоточности, однако я не уверен. Пожалуйста, просветите меня. Спасибо.


person kstratis    schedule 11.11.2013    source источник
comment
Третий ответ на этот вопрос объясняет это подробно.   -  person Luiggi Mendoza    schedule 11.11.2013


Ответы (3)


finally выполняется перед оператором return. Поскольку правило java finally будет выполняться всегда, за исключением случаев, когда происходит сбой JVM или вызывается System.exit().

Спецификация языка Java четко упоминает выполнение finally в разных условиях:

http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.2

person Juned Ahsan    schedule 11.11.2013
comment
В документах указано, что если в методе или конструкторе есть какие-либо операторы try, блоки try которых содержат оператор return, то все предложения finally этих операторов try будут выполняться в порядке от самого внутреннего к внешнему, прежде чем управление будет передано вызывающей стороне. метод или конструктор. Если я изменю свой код в блоке try на return 0;, тогда моя консоль напечатает «Это блок finally», а затем 0. Однако, если я поставлю оператор печати перед return 0;, тогда порядок будет таким: «Это блок finally», а затем 0. Я запутался - person kstratis; 11.11.2013

Оператор return не влияет на выполнение блока finally. Блок finally не выполняется только в том случае, если блок JVM аварийно завершает работу до выполнения блока finally. Проверьте эту ссылку, чтобы узнать больше. Итак, если ваш код заменен на

try{
  System.exit(0);
}
catch(SomeException e){
  System.out.println(e);
}
finally{
  System.out.println("This is the finally block");
}

Блок finally не будет выполняться

person Prateek    schedule 11.11.2013

Джун прав. Я также хотел предостеречь от создания исключений из блоков finally, они будут обрабатывать другие возникающие исключения. Например (несколько глупый пример, но он имеет смысл):

boolean ok = false;
try {
   // code that might throw a SQLException
   ok = true;
   return;
}
catch (SQLException e) {
   log.error(e);
   throw e;
}
finally {
   if (!ok) {
      throw new RuntimeException("Not ok");
   }
}

В этом случае, даже когда SQLException перехвачено и повторно выброшено, finally генерирует здесь RuntimeException, и оно «маскирует» или переопределяет SQLException. Вызывающий объект получит RuntimeException, а не SQLException.

person brettw    schedule 11.11.2013