Задачки с собеседований и не только

Материал в этом посте справедлив для многих языков программирования. Но, как всегда, примеры буду показывать на JS, так как мне просто нравится это магический, напичканный костылями, язык ☺

В мире программирования есть общие вопросы, которые задаются на разные позиции в разных областях. Один из таких вопросов: как работает перехват исключений, а именно рассказать как поведет себя блок:

try {} catch {} finally {}

Многие знают как ловить исключения и как работает блок try/catch. Но вот добавление блока finally может сильно поменять логику и, даже, удивить, если не знать правил его работы. Этот вопрос можно услышать на собеседовании по Java, C#, PHP и нашем любимом JavaScript.

Вроде бы не такой-то уж и сложный вопрос, но в нем легко запутаться. Рассмотрим такой случай:


Что вернется? В принципе все просто, вернется 2, так мы выбросили исключение, то отработает блок catch и из него будет возврат.

Что если добавить блок finally ?


Здесь уже интереснее и вы видите, что даже если в блоке catch есть возврат, то он игнорируется и возврат происходит из блока finally.

Finally и success

А что если у нас не выбрасывается исключение?


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

"try block"
"finally block"
5

Да, у нас блок finally отрабатывает всегда.

Усложняем вопрос: 2 блока finally


Ответ: после первого блока finally далее уже код не будет отрабатываться (если мы выходим из блока через return)и там может быть все что угодно.

Выносим return из finally блока, и что же будет тогда?


Ответ:

"try block"
"finally block"
1

Возврат будет из блока try, но finally будет отрабатывать всегда, так что в этом блоке можно даже что-то еще посчитать хоть ответ уже и вернулся:


А как отработает такой Node.js код?

Интересный вопрос, м?


Как мы видим тут уже исключение в исключении. Код отработает точно так же, как и, к примеру, в Java. В Java вызов System.exit() не позволяет сработать блоку finally.

В Node.js аналогичная ситуация: process.exit() не дает отработать блоку finally.

Для тех, кто пишет на PHP, вопрос как отработает этот код:

<?php declare(strict_types=1);
try {
var_dump('try');
foo();
}
catch (Error $e) {
var_dump('catch');
exit(1);
}
finally {
var_dump('finally');
}

Ответ не даю. Догадаетесь сами 🙂