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

Как обрабатываются ошибки в Java?

1.2 Junior🔥 241 комментариев
#Основы Java

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

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

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

Обработка ошибок в Java

Обработка ошибок (Exception Handling) — критически важный аспект разработки на Java. Java использует механизм исключений (exceptions) для обработки ошибочных ситуаций, позволяя приложению продолжить работу или корректно завершиться вместо краха.

Иерархия Exception в Java

Throwable
├── Error (критические ошибки JVM)
│   ├── OutOfMemoryError
│   ├── StackOverflowError
│   └── LinkageError
└── Exception (обработанные исключения)
    ├── IOException (checked)
    ├── SQLException (checked)
    ├── RuntimeException (unchecked)
    │   ├── NullPointerException
    │   ├── ArithmeticException
    │   ├── ArrayIndexOutOfBoundsException
    │   └── IllegalArgumentException
    └── Custom exceptions

Основной механизм: try-catch-finally

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

Порядок catch блоков

Каждение от специального к общему — это ВАЖНО:

try {
    // ...
} catch (FileNotFoundException e) {
    // Специальный случай
} catch (IOException e) {
    // Более общий случай (IOException — родитель FileNotFoundException)
} catch (Exception e) {
    // Самый общий случай
}

Checked vs Unchecked Exception

Checked Exception — проверяются на этапе компиляции:

public void readFile(String path) throws IOException {
    FileReader reader = new FileReader(path);  // IOException — checked
    // Либо throw, либо обработать в try-catch
}

Unchecked Exception — не проверяются при компиляции:

int value = Integer.parseInt("abc");  // NumberFormatException
// Не нужно объявлять throws

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

// Checked exception
public class InvalidUserException extends Exception {
    public InvalidUserException(String message) {
        super(message);
    }
    
    public InvalidUserException(String message, Throwable cause) {
        super(message, cause);
    }
}

// Unchecked exception
public class ValidationException extends RuntimeException {
    public ValidationException(String message) {
        super(message);
    }
}

// Использование
public void validateUser(User user) throws InvalidUserException {
    if (user == null) {
        throw new InvalidUserException("User cannot be null");
    }
}

Try-with-resources (Java 7+)

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

// Старый способ
FileReader reader = null;
try {
    reader = new FileReader("file.txt");
    // работа с файлом
} finally {
    if (reader != null) {
        reader.close();  // Может выбросить IOException
    }
}

// Новый способ (более безопасный)
try (FileReader reader = new FileReader("file.txt")) {
    // работа с файлом
} catch (IOException e) {
    System.out.println("Ошибка: " + e.getMessage());
}
// reader закроется автоматически

Multi-catch (Java 7+)

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

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

1. Не игнорируй исключения

// ❌ ПЛОХО
try {
    // код
} catch (Exception e) {
    // молчим
}

// ✅ ХОРОШО
try {
    // код
} catch (IOException e) {
    logger.error("Failed to read file", e);
    throw new ApplicationException("File processing failed", e);
}

2. Используй специальные исключения

// ❌ Слишком общее
throw new Exception("Invalid input");

// ✅ Специфичное
throw new IllegalArgumentException("Email format is invalid");

3. Логируй с контекстом

try {
    processPayment(orderId, amount);
} catch (PaymentException e) {
    logger.error("Payment failed for order {} with amount {}", orderId, amount, e);
}

4. Не перехватывай Exception.class

// ❌ Перехватит даже OutOfMemoryError
try {
    // код
} catch (Exception e) {
    // ...
}

// ✅ Перехватывай конкретные исключения
try {
    // код
} catch (IOException | SQLException e) {
    // ...
}

Стекинг исключений (Exception Chaining)

public void saveUser(User user) throws ApplicationException {
    try {
        database.save(user);
    } catch (SQLException e) {
        // Оборачиваем checked exception в unchecked
        throw new ApplicationException("Failed to save user: " + user.getId(), e);
    }
}

// Причина исключения сохраняется и может быть получена
ApplicationException ae = ...;
throwable.getCause();  // Вернет исходную SQLException

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