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