← Назад к вопросам
Как знаешь способы, перехватить общее исключение Exception в handler, извлечь и работать с конкретной ошибкой, которая является экземпляром моего пользовательского исключения
1.0 Junior🔥 201 комментариев
#SOLID и паттерны проектирования#Spring Framework#Основы Java
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Перехват и обработка пользовательских исключений
Перехват общего исключения Exception и последующая работа с конкретным пользовательским исключением — это важный паттерн обработки ошибок в Java. Рассмотрю несколько способов реализации.
1. Использование instanceof для проверки типа
Это наиболее распространённый и рекомендуемый способ:
// Пользовательское исключение
public class PaymentException extends Exception {
private String paymentMethod;
private BigDecimal amount;
public PaymentException(String message, String paymentMethod, BigDecimal amount) {
super(message);
this.paymentMethod = paymentMethod;
this.amount = amount;
}
public String getPaymentMethod() {
return paymentMethod;
}
public BigDecimal getAmount() {
return amount;
}
}
// Код, который может выбросить исключение
public class PaymentService {
public void processPayment(String method, BigDecimal amount) throws PaymentException {
if (amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new PaymentException("Сумма должна быть положительной", method, amount);
}
}
}
// Обработка в handler
try {
paymentService.processPayment("CREDIT_CARD", new BigDecimal("100"));
} catch (Exception e) {
if (e instanceof PaymentException) {
PaymentException paymentError = (PaymentException) e;
System.out.println("Ошибка платежа: " + paymentError.getMessage());
System.out.println("Метод: " + paymentError.getPaymentMethod());
System.out.println("Сумма: " + paymentError.getAmount());
// Дополнительная обработка
} else {
// Обработка других типов исключений
System.err.println("Неизвестная ошибка: " + e.getMessage());
}
}
2. Pattern matching (Java 16+)
Современный и более элегантный способ:
try {
paymentService.processPayment("CREDIT_CARD", new BigDecimal("100"));
} catch (Exception e) {
if (e instanceof PaymentException paymentError) {
// Переменная paymentError доступна в этом блоке
System.out.println("Метод: " + paymentError.getPaymentMethod());
System.out.println("Сумма: " + paymentError.getAmount());
} else {
System.err.println("Неизвестная ошибка: " + e.getMessage());
}
}
3. Специфичные catch блоки (рекомендуется)
Лучший подход — ловить конкретные исключения в нужном порядке:
try {
paymentService.processPayment("CREDIT_CARD", new BigDecimal("100"));
} catch (PaymentException e) {
// Обработка платёжных ошибок
System.out.println("Ошибка платежа: " + e.getMessage());
System.out.println("Метод: " + e.getPaymentMethod());
notifyPaymentFailure(e);
} catch (IOException e) {
// Обработка ошибок ввода-вывода
System.err.println("Ошибка соединения: " + e.getMessage());
} catch (Exception e) {
// Обработка всех остальных ошибок
System.err.println("Неизвестная ошибка: " + e.getMessage());
e.printStackTrace();
}
4. Иерархия пользовательских исключений
Для лучшей организации создавайте иерархию:
// Базовое пользовательское исключение
public class BusinessException extends Exception {
private String errorCode;
public BusinessException(String message, String errorCode) {
super(message);
this.errorCode = errorCode;
}
public String getErrorCode() {
return errorCode;
}
}
// Специфичные исключения
public class PaymentException extends BusinessException {
private String paymentMethod;
public PaymentException(String message, String errorCode, String paymentMethod) {
super(message, errorCode);
this.paymentMethod = paymentMethod;
}
public String getPaymentMethod() {
return paymentMethod;
}
}
public class ValidationException extends BusinessException {
public ValidationException(String message, String errorCode) {
super(message, errorCode);
}
}
// Обработка иерархии
try {
processPayment();
} catch (PaymentException e) {
handlePaymentError(e);
} catch (ValidationException e) {
handleValidationError(e);
} catch (BusinessException e) {
handleBusinessError(e);
} catch (Exception e) {
handleSystemError(e);
}
5. Использование метода getCause()
Для работы с цепочками исключений:
try {
someOperation();
} catch (Exception e) {
if (e instanceof PaymentException) {
PaymentException paymentError = (PaymentException) e;
// Проверка корневой причины
Throwable cause = e.getCause();
if (cause instanceof TimeoutException) {
System.out.println("Таймаут при обработке платежа");
} else if (cause instanceof NetworkException) {
System.out.println("Ошибка сети");
}
}
}
6. Практический пример с логированием
@Service
public class OrderService {
private static final Logger logger = LoggerFactory.getLogger(OrderService.class);
public Order createOrder(OrderRequest request) {
try {
validateOrder(request);
processPayment(request.getAmount());
return saveOrder(request);
} catch (PaymentException e) {
logger.warn("Ошибка платежа для метода: {}", e.getPaymentMethod(), e);
throw e; // Прокидываем дальше или преобразуем
} catch (ValidationException e) {
logger.error("Ошибка валидации: {}", e.getMessage(), e);
throw new BadRequestException(e.getMessage(), e.getErrorCode());
} catch (Exception e) {
logger.error("Критическая ошибка при создании заказа", e);
throw new InternalServerException("Не удалось создать заказ", e);
}
}
}
Лучшие практики
- Ловь конкретные исключения, а не общие Exception
- Используй instanceof для проверки типа и pattern matching в Java 16+
- Создавай иерархию пользовательских исключений для лучшей организации
- Логируй исключения с полной информацией о контексте
- Не глуши исключения — либо обработай, либо прокинь дальше
- Используй getCause() для анализа цепочки исключений
- Добавляй контекстную информацию в пользовательские исключения (как в примере с PaymentException)