Для чего нужен finally в try…catch

В PHP, начиная с версии 5.5, а в JavaScript с редакции 1.4 есть поддержка обработки с исключений с помощью конструкций try…catch…finally.

Для многих остается загадкой, в чем же функция этого «finally«. В документации написано, что код в блоке finally будет выполнен независимо от того, было ли вызвано исключение в блоке try. Напомню, что код в блоке try выполняется до конца блока или до тех пор, пока не будет вызвано исключение, а в этом случае выполняется код в блоке catch. То есть, на первый взгляд блок finally избыточен, ведь если мы хотим, чтобы код выполнился в любом случае после try и catch, достаточно просто разместить этот код после них. Во многих случаях это действительно так, но есть несколько случаев, когда finally может быть полезен.

Важно пояснить, что finally выполнится в любом случае перед выходом из конструкции try/catch/finally, то есть это пригодится для обработки ситуаций, когда блок catch не отработал, а исключение возникло. Например, если блока catch нет вообще или в подобной ситуации, когда ожидается исключение определенного вида, а вызывается другое:

То есть мы можем как-то среагировать на такую кажущуюся «неуправляемой» ситуацию перед тем, как исключение уйдет на верхний уровень.

В случае вложенных исключений, если блоки finally в них присутствуют, то код будет выполнен во всех таких блоках последовательно, начиная с самого «глубокого» уровня. Например:

Блоки finally могут быть полезны при соединении с базой данных или со сторонним API, когда, например, у вас может быть многоэтапная обработка исключений, но при этом важно при любом исходе закрыть соединение или какой-то ресурс — такие процедуры безусловного «завершения» или «очистки» как раз удобно размещать в finally.

Особое внимание при работе с try/catch/finally надо уделить оператору return внутри блоков. Поскольку finally выполнится в любом случае до выхода из try/catch, то любые return в этих блоках выполнятся тоже только после finally, и если finally также будет содержать return, то окончательно возвращаемое значение будет именно тем, что указано после return в finally. При этом, если выход из try/catch/finally произойдет по return, то исключение не передастся дальше, а продолжится нормальный ход выполнения программы, как если бы исключение было успешно обработано.

Как уже было отмечено, в finally можно поместить операции «завершения» чего-либо. Например, это очень удобно делать для закрытия файловых потоков или «подчистку» после обращений к внешним API.

Например, для закрытия потоков хороший пример написан в статье Frank de Jonge:

Код без с использования finally:

Код с использованием finally:

То есть мы избавились от копипасты закрытия потока, и проводим эту рутинную операцию в одном месте.

 

Поделиться: Share on LinkedIn
Linkedin
Share on VK
VK
Share on Facebook
Facebook
0Share on Google+
Google+
0Tweet about this on Twitter
Twitter

Оставить комментарий

Ваш e-mail не будет опубликован.

Яндекс.Метрика