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

Какие знаешь способы обработки ошибки типа Error?

2.0 Middle🔥 161 комментариев
#REST API и микросервисы#Spring Framework

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Способы обработки ошибок типа Error в Java

Знание обработки ошибок критически важно для создания надежных приложений. Рассмотрю основные способы:

1. Иерархия Throwable

Throwable
├── Exception (checked)
│   ├── IOException
│   ├── SQLException
│   └── CustomException
├── RuntimeException (unchecked)
│   ├── NullPointerException
│   ├── IllegalArgumentException
│   └── IndexOutOfBoundsException
└── Error (системные ошибки)
    ├── OutOfMemoryError
    ├── StackOverflowError
    └── NoClassDefFoundError

2. Try-Catch блоки

Базовая обработка

try {
    // Код, который может выбросить исключение
    int result = 10 / 0;
} catch (ArithmeticException e) {
    // Обработка конкретного исключения
    System.err.println("Деление на ноль: " + e.getMessage());
} catch (Exception e) {
    // Обработка более общих исключений
    System.err.println("Неизвестная ошибка");
} finally {
    // Выполняется всегда, даже если было исключение
    System.out.println("Очистка ресурсов");
}

Multiple catch блоки (Java 7+)

try {
    riskyOperation();
} catch (IOException | SQLException | TimeoutException e) {
    logger.error("Ошибка операции: " + e.getMessage(), e);
    // Обработка нескольких типов исключений
}

3. Try-with-Resources (Java 7+)

Автоматическое закрытие ресурсов:

// Плохо - риск утечки ресурса
BufferedReader reader = new BufferedReader(new FileReader("file.txt"));
try {
    String line = reader.readLine();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    reader.close(); // Может не выполниться
}

// Хорошо - гарантированное закрытие
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
    String line = reader.readLine();
} catch (IOException e) {
    logger.error("Ошибка чтения файла", e);
}

4. Throws декларация

Передача ответственности вызывающему коду:

public void readFile(String path) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader(path));
    // Не обрабатываем IOException, пробрасываем дальше
}

public void processFile() {
    try {
        readFile("data.txt");
    } catch (IOException e) {
        // Здесь обрабатываем
    }
}

5. Custom Exceptions

Создание собственных исключений для конкретных ошибок:

public class InsufficientFundsException extends Exception {
    private final BigDecimal requiredAmount;
    private final BigDecimal availableAmount;
    
    public InsufficientFundsException(BigDecimal required, BigDecimal available) {
        super(String.format("Требуется %s, доступно %s", required, available));
        this.requiredAmount = required;
        this.availableAmount = available;
    }
}

public void withdraw(BigDecimal amount) throws InsufficientFundsException {
    if (amount.compareTo(balance) > 0) {
        throw new InsufficientFundsException(amount, balance);
    }
    balance = balance.subtract(amount);
}

6. Try-Catch с логированием

Практический подход:

public UserProfile getUserProfile(String userId) {
    try {
        return userService.getProfile(userId);
    } catch (UserNotFoundException e) {
        logger.warn("Пользователь не найден: " + userId);
        return createDefaultProfile(userId);
    } catch (DatabaseException e) {
        logger.error("Ошибка БД при получении профиля пользователя", e);
        throw new ServiceException("Временно недоступно, попробуйте позже", e);
    } catch (Exception e) {
        logger.error("Непредвиденная ошибка", e);
        throw new ServiceException("Внутренняя ошибка сервера", e);
    }
}

7. Optional вместо null checks

Современный подход (Java 8+):

// Старый способ
User user = findUser(id);
if (user != null) {
    System.out.println(user.getName());
}

// Новый способ
findUserOptional(id)
    .ifPresentOrElse(
        user -> System.out.println(user.getName()),
        () -> System.out.println("Пользователь не найден")
    );

8. Специальные случаи

OutOfMemoryError

Ошибка памяти обычно не обрабатывается, так как она критична:

try {
    List<String> list = new ArrayList<>();
    while (true) {
        list.add("memory");
    }
} catch (OutOfMemoryError e) {
    // В 99% случаев лучше завершить приложение
    System.exit(1);
}

StackOverflowError

private void recursiveMethod(int depth) {
    try {
        if (depth > 1000) {
            throw new IllegalArgumentException("Глубина рекурсии превышена");
        }
        recursiveMethod(depth + 1);
    } catch (StackOverflowError e) {
        logger.error("Переполнение стека вызовов", e);
    }
}

9. Best Practices

Не ловите слишком общие исключения:

// Плохо
try {
    // код
} catch (Exception e) { }

// Хорошо
try {
    // код
} catch (SpecificException e) {
    // обработка
}

Всегда логируйте исключения:

catch (IOException e) {
    logger.error("Ошибка ввода-вывода при обработке файла", e);
    // Не просто e.printStackTrace()
}

Предоставляйте контекст:

try {
    user = userRepository.findById(userId);
} catch (DatabaseException e) {
    throw new ServiceException("Не удалось загрузить пользователя ID=" + userId, e);
}

Заключение

Обработка ошибок требует баланса между безопасностью и читаемостью. Используйте конкретные исключения, логируйте ошибки, предоставляйте контекст и избегайте молчаливой обработки исключений. Error-ы обычно не обрабатываются — это указания на критические проблемы.

Какие знаешь способы обработки ошибки типа Error? | PrepBro