Что произойдет, если исключение будет выброшено в блоке finally?

«Что произойдет, если исключение будет выброшено в блоке finally?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Исключение в блоке finally «замещает» (masks) исключение, выброшенное в блоках try или catch. Вызывающий код получит только исключение из finally, а исходное будет потеряно.

Пример потери исходного исключения:

try {
    throw new IOException("Ошибка при чтении файла");
} finally {
    throw new RuntimeException("Неожиданная ошибка при закрытии ресурса");
}
// Будет выброшено RuntimeException, а IOException — потеряно.

Как правильно обрабатывать:

  1. Аккуратный finally: Блок finally должен быть максимально безопасным и по возможности не выбрасывать исключения.
  2. Использование addSuppressed() (Java 7+): При реализации AutoCloseable можно добавить исключение из finally как подавленное (suppressed) к основному.
    try (MyResource resource = new MyResource()) {
        throw new IOException("Ошибка в try");
    }
    // Если и в try, и в close() есть исключения,
    // исключение из close() станет suppressed для исключения из try.
  3. Логирование: Если исключение в finally неизбежно, залогируйте его перед повторным выбросом, чтобы сохранить информацию.