← Назад к вопросам

Как знаешь способы, перехватить общее исключение 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);
        }
    }
}

Лучшие практики

  1. Ловь конкретные исключения, а не общие Exception
  2. Используй instanceof для проверки типа и pattern matching в Java 16+
  3. Создавай иерархию пользовательских исключений для лучшей организации
  4. Логируй исключения с полной информацией о контексте
  5. Не глуши исключения — либо обработай, либо прокинь дальше
  6. Используй getCause() для анализа цепочки исключений
  7. Добавляй контекстную информацию в пользовательские исключения (как в примере с PaymentException)