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

Используешь ли Exception

2.0 Middle🔥 161 комментариев
#Основы Java

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

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

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

# Использование Exceptions в Java

Да, я активно использую исключения, но придерживаюсь определённых принципов и лучших практик.

Иерархия исключений

Любое исключение в Java наследуется от Throwable. На практике работаю с:

  • Checked Exceptions (наследуют Exception) — компилятор их отслеживает, должны быть обработаны или пробрасываются далее. Используются для восстанавливаемых ошибок: IOException, SQLException, FileNotFoundException.

  • Unchecked Exceptions (наследуют RuntimeException) — не требуют обязательной обработки. Обычно указывают на ошибки программиста: NullPointerException, IndexOutOfBoundsException, IllegalArgumentException.

Когда я использую Exceptions

// ✅ Правильно: исключение для исключительной ситуации
public User findUserById(String userId) throws UserNotFoundException {
    return userRepository.findById(userId)
        .orElseThrow(() -> new UserNotFoundException("User not found: " + userId));
}

// ❌ Неправильно: исключение для нормального управления потоком
if (users.size() == 0) {
    throw new EmptyCollectionException(); // Плохая практика
}

// ✅ Правильно: использовать return или Optional
if (users.isEmpty()) {
    return null; // или Optional.empty()
}

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

1. Создание собственных исключений

Для специфичных ошибок создаю свои исключения, наследующие Exception:

public class UserNotFoundException extends Exception {
    public UserNotFoundException(String message) {
        super(message);
    }
    
    public UserNotFoundException(String message, Throwable cause) {
        super(message, cause);
    }
}

2. Правильный стек вызовов (Exception Chaining)

try {
    database.connect();
} catch (SQLException e) {
    // Оборачиваю исходное исключение, сохраняя контекст
    throw new DataAccessException("Failed to connect to database", e);
}

3. Информативные сообщения об ошибках

// ❌ Плохо
throw new Exception("Error");

// ✅ Хорошо
throw new InvalidInputException(
    String.format("User ID must be positive, got: %d", userId)
);

4. Try-with-resources для автоматического закрытия ресурсов

// ✅ Лучше: автоматически закроет файл
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
    String line = reader.readLine();
} catch (IOException e) {
    logger.error("Failed to read file", e);
}

5. Логирование

try {
    processOrder(order);
} catch (OrderProcessingException e) {
    // Логирую на нужном уровне (не дублирую логирование на разных слоях)
    logger.error("Order processing failed for ID: {}", orderId, e);
    throw e; // Или обрабатываю локально
}

Когда НЕ использую Exceptions

  • Для обычного потока выполнения (control flow)
  • Для вернуться на несколько уровней вверх без обработки
  • Вместо проверок параметров на входе

Обработка исключений

// ✅ Специфичная обработка
try {
    service.execute();
} catch (NotFoundException e) {
    return ResponseEntity.notFound().build();
} catch (ValidationException e) {
    return ResponseEntity.badRequest().body(e.getMessage());
} catch (Exception e) {
    logger.error("Unexpected error", e);
    return ResponseEntity.status(500).build();
}

// ❌ Плохо: ловлю все сразу
try {
    service.execute();
} catch (Exception e) {
    e.printStackTrace();
}

Заключение

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

Используешь ли Exception | PrepBro