Каковы преимущества использования пользовательских (кастомных) исключений в Java?

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

Ответ

Пользовательские исключения (наследники Exception или RuntimeException) используются для точного отражения специфических ошибок предметной области (бизнес-логики).

Преимущества перед стандартными исключениями:

  1. Семантическая ясность: Имя исключения прямо указывает на суть проблемы (например, UserNotFoundException vs общее IllegalArgumentException).
  2. Лучшая обработка: Позволяют точечно отлавливать конкретные сценарии сбоев.
  3. Расширяемость: Можно добавить дополнительные поля, методы или логику.

Пример создания и использования:

// 1. Определение кастомного проверяемого исключения
class InsufficientFundsException extends Exception {
    private double deficit;

    public InsufficientFundsException(String message, double deficit) {
        super(message);
        this.deficit = deficit;
    }

    public double getDeficit() { return deficit; }
}

// 2. Использование в сервисе
class BankAccount {
    private double balance;

    public void withdraw(double amount) throws InsufficientFundsException {
        if (amount > balance) {
            double deficit = amount - balance;
            // Бросаем понятное исключение с контекстом
            throw new InsufficientFundsException("Withdrawal amount exceeds balance", deficit);
        }
        balance -= amount;
    }
}

// 3. Четкая обработка на верхнем уровне
public class Main {
    public static void main(String[] args) {
        BankAccount account = new BankAccount();
        try {
            account.withdraw(1000);
        } catch (InsufficientFundsException e) {
            // Обрабатываем именно ошибку недостатка средств
            System.err.println("Operation failed: " + e.getMessage());
            System.err.println("You need " + e.getDeficit() + " more.");
        }
    }
}