Иерархия исключений: зачем ловить конкретный класс, а не Throwable

catch (Throwable t) ловит вообще всё, включая Error — OutOfMemoryError, StackOverflowError. Кандидат, который так пишет «для надёжности», обычно объясняет это желанием ничего не пропустить. На собеседовании это минус, а не плюс.

Error сигнализирует о состоянии, из которого JVM обычно не может корректно восстановиться. Если поймать OutOfMemoryError и попытаться продолжить работу — логика приложения окажется в непредсказуемом состоянии: часть объектов создалась, часть нет, инварианты нарушены.

Правильная иерархия перехвата — конкретные исключения, которые вы действительно умеете обрабатывать. Универсальный catch (Exception e) на границе приложения — не для восстановления, а для логирования и корректного ответа клиенту, и это осознанное архитектурное решение, а не привычка ловить всё подряд.

try { orderService.process(order); } catch (PaymentDeclinedException e) { return ResponseEntity .status(402) .body(e.getMessage()); } catch (ValidationException e) { return ResponseEntity .badRequest() .body(e.getMessage()); }

Ловушка: если после catch (Exception e) стоит catch (RuntimeException e) ниже — код не компилируется. Exception шире RuntimeException, и компилятор считает второй блок недостижимым. Порядок catch-блоков должен идти от более узкого класса к более широкому.

Широта перехвата исключений — это не про удобство, а про то, какие состояния системы вы готовы признать восстанавливаемыми.

Тренажёр: 600 вопросов, мок с таймером, план повторов

senior·base — что спрашивают на самом деле


В этом посте были ссылки, но мы их удалили по правилам Сетки