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

Исключение (exception) — это событие, возникающее во время выполнения программы и нарушающее нормальный поток её работы. Когда внутри метода происходит ошибка, метод создаёт объект-исключение и передаёт его системе времени выполнения. Этот процесс называется «выбрасыванием исключения» (throwing an exception).

Механизм исключений в Java позволяет отделить обычный код от кода обработки ошибок, что делает программу более читаемой и устойчивой. Все исключения являются наследниками класса Throwable, от которого происходят два главных потомка: Error (критические ошибки JVM) и Exception (ошибки прикладного уровня, с которыми программа может справиться).

В контексте AlashEd-проектов исключения часто встречаются при чтении конфигурационных файлов датчиков, парсинге логов с Arduino через Serial и работе с сетевыми соединениями ESP32.

Иерархия классов

Throwable
├── Error              (OutOfMemoryError, StackOverflowError) — не ловим
└── Exception
    ├── RuntimeException   (unchecked — NullPointerException, ArithmeticException...)
    └── IOException, SQLException... (checked — компилятор требует обработку)

Синтаксис базовой обработки

try {
    // код, который может выбросить исключение
} catch (ТипИсключения e) {
    // обработка
} finally {
    // выполнится в любом случае
}

Пример 1. Деление на ноль

public class DivideExample {
    public static void main(String[] args) {
        try {
            int result = 10 / 0;
            System.out.println("Результат: " + result);
        } catch (ArithmeticException e) {
            System.out.println("Ошибка: " + e.getMessage());
        }
        System.out.println("Программа продолжает работу");
    }
}

Output:

Ошибка: / by zero
Программа продолжает работу

Пример 2. NullPointerException

public class NullExample {
    public static void main(String[] args) {
        String sensorName = null;
        try {
            int length = sensorName.length();
            System.out.println("Длина: " + length);
        } catch (NullPointerException e) {
            System.out.println("Имя датчика не задано");
        }
    }
}

Output:

Имя датчика не задано

Пример 3. Несколько catch-блоков

public class MultiCatch {
    public static void main(String[] args) {
        String[] data = {"23.5", "abc", "18.2"};
        for (int i = 0; i <= data.length; i++) {
            try {
                double t = Double.parseDouble(data[i]);
                System.out.println("Температура: " + t);
            } catch (NumberFormatException e) {
                System.out.println("Не число: " + data[i]);
            } catch (ArrayIndexOutOfBoundsException e) {
                System.out.println("Выход за границы массива");
            }
        }
    }
}

Output:

Температура: 23.5
Не число: abc
Температура: 18.2
Выход за границы массива

Пример 4. Получение информации об исключении

public class ExceptionInfo {
    public static void main(String[] args) {
        try {
            int[] readings = new int[3];
            readings[10] = 42;
        } catch (Exception e) {
            System.out.println("Класс:    " + e.getClass().getSimpleName());
            System.out.println("Сообщение: " + e.getMessage());
            System.out.println("toString: " + e);
        }
    }
}

Output:

Класс:    ArrayIndexOutOfBoundsException
Сообщение: Index 10 out of bounds for length 3
toString: java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 3

Пример 5. Блок finally

public class FinallyExample {
    public static void main(String[] args) {
        try {
            System.out.println("Открыли соединение с датчиком");
            int v = Integer.parseInt("xx");
            System.out.println("Значение: " + v);
        } catch (NumberFormatException e) {
            System.out.println("Ошибка парсинга");
        } finally {
            System.out.println("Закрыли соединение с датчиком");
        }
    }
}

Output:

Открыли соединение с датчиком
Ошибка парсинга
Закрыли соединение с датчиком

Подводные камни

Предупреждение

  • Не ловите ``Exception`` или ``Throwable`` без необходимости — это маскирует баги.

  • Пустой ``catch``-блок — антипаттерн: ошибка теряется молча.

  • Порядок ``catch`` имеет значение: более конкретные исключения сначала, общие — потом.

  • ``finally`` выполняется даже после ``return`` в try/catch.

  • ``Error`` обычно не ловят: их возникновение означает, что JVM не может продолжать работу.

См. также

Примечание

Материал подготовлен на основе официальной документации Oracle Java Tutorials — Lesson: Exceptions (Oracle Free Documentation License). Текст переведён и переработан, примеры кода написаны заново.