Добавить в корзинуПозвонить
Найти в Дзене
Записки о Java

Исключения в Java: Полное руководство с примерами и объяснениями

Исключения — фундаментальная часть языка Java, которая позволяет корректно обрабатывать ошибки и непредвиденные ситуации во время выполнения программы. Понимание того, как работают исключения, помогает писать более надёжный, читаемый и поддерживаемый код. В этой статье мы разберём: Исключение — это событие, которое нарушает нормальный поток выполнения программы. В Java все исключения являются объектами классов, унаследованных от базового класса java.lang.Throwable. Пример простого исключения: Этот код вызовет исключение ArithmeticException, потому что деление на ноль недопустимо. Все исключения в Java наследуются от Throwable, который имеет два основных подкласса: Класс Exception делится на два типа: Throwable ├── Error └── Exception ├── RuntimeException ← unchecked └── IOException ← checked └── FileNotFoundException ← checked Пример: Здесь FileNotFoundException — проверяемое исключение. Если не обработать его или не объявить в сигнатуре метода с throws, код не с
Оглавление
Рисунок: Исключения в Java
Рисунок: Исключения в Java

Введение

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

  • Что такое исключения в Java
  • Иерархию исключений
  • Разницу между проверяемыми и непроверяемыми исключениями
  • Как использовать try-catch-finally и try-with-resources
  • Лучшие практики обработки исключений

Что такое исключение?

Исключение — это событие, которое нарушает нормальный поток выполнения программы. В Java все исключения являются объектами классов, унаследованных от базового класса java.lang.Throwable.

Пример простого исключения:

Рисунок: пример простого исключения
Рисунок: пример простого исключения

Этот код вызовет исключение ArithmeticException, потому что деление на ноль недопустимо.

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

Все исключения в Java наследуются от Throwable, который имеет два основных подкласса:

  • Error — указывает на серьёзные системные ошибки, которые не следует обрабатывать в коде приложения (например, OutOfMemoryError).
  • Exception — представляет условия, которые программа может и должна обрабатывать.

Класс Exception делится на два типа:

  1. Проверяемые исключения (Checked Exceptions) — наследуются от Exception, но не от RuntimeException. Компилятор требует их обрабатывать или объявлять с помощью throws.
  2. Непроверяемые исключения (Unchecked Exceptions) — наследуются от RuntimeException. Не требуют обязательной обработки.

Throwable

├── Error

└── Exception

├── RuntimeException ← unchecked

└── IOException ← checked

└── FileNotFoundException ← checked

Проверяемые и непроверяемые исключения

Проверяемые исключения (Checked)

Пример:

Рисунок: пример проверяемого исключения
Рисунок: пример проверяемого исключения

Здесь FileNotFoundException — проверяемое исключение. Если не обработать его или не объявить в сигнатуре метода с throws, код не скомпилируется.

Непроверяемые исключения (Unchecked)

Пример:

Рисунок: пример непроверяемого исключения
Рисунок: пример непроверяемого исключения

NullPointerException — это RuntimeException, и компилятор не заставляет нас его обрабатывать. Однако хорошая практика — обрабатывать или предотвращать такие ситуации.

Блоки try-catch-finally

try-catch

Используется для перехвата и обработки исключений:

try {

// код, который может выбросить исключение

} catch (SpecificException e) {

// обработка исключения

}

Можно перехватывать несколько типов исключений:

try {

// ...

} catch (IOException e) {

// обработка IOException

} catch (SQLException e) {

// обработка SQLException

}

Или использовать мульти-catch (Java 7+):

catch (IOException | SQLException e) {

System.err.println("Ошибка ввода-вывода или базы данных: " + e.getMessage());

}

finally

Блок finally выполняется всегда, независимо от того, было ли исключение или нет:

Рисунок: пример работы с блоком finally
Рисунок: пример работы с блоком finally

try-with-resources (Java 7+)

Если ресурс реализует интерфейс AutoCloseable (например, FileReader, InputStream, Connection), его можно автоматически закрывать:

try (FileReader reader = new FileReader("file.txt")) {

// работа с reader

} catch (IOException e) {

e.printStackTrace();

}

// reader автоматически закрывается, даже если возникло исключение

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

Вы можете создавать собственные типы исключений, наследуясь от Exception (для проверяемых) или RuntimeException (для непроверяемых):

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

Лучшие практики обработки исключений

  1. Не игнорируйте исключения. Даже если вы не можете их обработать, залогируйте.java123⌄catch (IOException e) {logger.error("Ошибка чтения файла", e);}
  2. Используйте конкретные типы исключений, а не ловите Exception или Throwable.
  3. Не подавляйте стек-трейс. Всегда передавайте исходное исключение в конструктор нового:java1throw new MyServiceException("Ошибка обработки", originalException);
  4. Используйте try-with-resources для автоматического освобождения ресурсов.
  5. Не используйте исключения для управления потоком выполнения. Это анти-паттерн и снижает производительность.
  6. Документируйте исключения в Javadoc с помощью @throws.

Заключение

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

Если вы работаете в команде, заранее договоритесь о стратегии обработки исключений: какие использовать, как логировать, когда оборачивать и когда пробрасывать.

Примеры, рассмотренные в статье, можно найти по адресу:
https://github.com/ShkrylAndrei/blog_yandex/tree/main/src/main/java/info/shkryl/exceptionInJava