Метод читает файл, в try бросается IOException, а в finally стоит return — и исключение исчезает, будто его не было. Это не редкость в легаси-коде, и на собеседовании проверяют, понимает ли кандидат механику, а не просто помнит правило "так делать нельзя".

Причина в байткоде: finally выполняется всегда, и если в нём есть return, JVM использует именно его как результат метода. Любое исключение, которое летело из try или catch, отбрасывается на этом моменте — оно не логируется, не оборачивается, просто пропадает.

То же самое происходит, если в finally есть break или continue — они тоже подавляют исключение. Любое резкое завершение управления в finally побеждает то, что происходило в try.

static int read() { try { throw new RuntimeException("boom"); } finally { return 42; // исключение потеряно, метод вернёт 42 } }

Спросят следом: а что если в finally не return, а просто вызов другого метода, который тоже бросает исключение? Ответ — тогда победит исключение из finally, а оригинальное из try станет suppressed только если используется try-with-resources с AutoCloseable. В обычном try-finally оригинальное исключение просто теряется без следа, никакого suppressed не будет.

Правило простое: в finally не должно быть return, break, continue или throw, если только это не специально задуманное поведение.

Тренажёр: 900+ вопросов и задач, мок с таймером, план повторов

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


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