Что произойдёт при выполнении этого Java‑кода и как правильно реализовать обработку исключений, чтобы не потерять первоначальную ошибку: public void example() { try { throw new RuntimeException("try"); } finally { throw new RuntimeException("finally"); } } — обсудите механизмы addSuppressed, try-with-resources и проектирование API для надёжной передачи ошибок

4 Ноя в 06:56
3 +1
0
Ответы
1
Что произойдёт
- При выполнении вашего кода будет выброшено исключение из блока finally. Исключение из try будет «перекрыто» и потеряно — JVM выбросит только RuntimeException("finally"), исходное RuntimeException("try") не будет видимо в стектрейсе.
Как правильно обрабатывать, чтобы не потерять первоначальную ошибку
1) Ручное добавление suppressed (Java 7+)
- Схема: сохранить первичное исключение, а при возникновении исключения в finally добавить его как suppressed к первичному и вернуть/перебросить первичное:
public void example() {
Throwable primary = null;
try {
throw new RuntimeException("try");
} catch (Throwable t) {
primary = t;
throw t;
} finally {
try {
throw new RuntimeException("finally");
} catch (Throwable t) {
if (primary != null) {
primary.addSuppressed(t);
} else {
throw t;
}
}
}
}
- Результат: выбрасывается первоначальное исключение ("try"), а исключение из finally ("finally") доступно через primary.getSuppressed().
2) try-with-resources (автоматическое подавление)
- Если ресурс реализует AutoCloseable и close() бросает исключение, Java автоматически добавит исключение из close() как suppressed к основному исключению из try. Это предпочтительный и безопасный способ управления ресурсами:
class R implements AutoCloseable {
public void close() throws Exception { throw new Exception("close"); }
}
public void example() throws Exception {
try (R r = new R()) {
throw new Exception("try");
}
}
// В этом случае "try" будет основным, "close" — suppressed.
3) Общие рекомендации по проектированию API и обработке ошибок
- Не бросайте новые исключения в finally без необходимости. Если нужно выполнить действия очистки, старайтесь, чтобы они не провоцировали исключения, или обрабатывайте их локально.
- Предпочитайте try-with-resources для управления ресурсами — это стандартный, безопасный и читабельный подход.
- Если метод обязан пробрасывать исключение из финализации/закрытия, документируйте порядок приоритета ошибок и используйте addSuppressed для сохранения вторичных исключений.
- Для передачи дополнительной информации рассмотрите использование suppressed, а не переприсваивания cause: initCause задаёт единственную причину и может скрыть более сложные ситуации; addSuppressed предназначен именно для «вторичных» ошибок.
- В тестах/логировании учитывайте getSuppressed() и printStackTrace(), которые покажут подавлённые исключения.
Краткое резюме
- Ваш код потеряет первоначальную ошибку: выбросится только "finally".
- Исправлять: либо не бросать в finally, либо сохранить/перебросить первоначальную ошибку и добавить вторичную через Throwable.addSuppressed, либо использовать try-with-resources для автоматической обработки suppressed.
4 Ноя в 07:28
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир