Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

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

Исключение (exception) — это объект, которым Java сообщает, что что-то пошло не так: деление на ноль, обращение за границу массива, отсутствующий файл. Когда исключение возникает, обычный ход программы прерывается. Если его никто не обработает, программа завершится и выведет описание ошибки.

Первое исключение

Поделим целое число на ноль:

void main() {
    int apples = 10;
    int people = 0;
 
    IO.println("Начинаем делить");
    IO.println(apples / people);
    IO.println("Эта строка не выполнится");
}

Результат:

Начинаем делить
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at Main.main(Main.java:6)

Первая строка успела вывестись, а после ошибки программа остановилась. Говорят, что код выбросил исключение (throw).

Как читать сообщение

Сообщение об исключении состоит из трёх частей:

  • java.lang.ArithmeticException — тип исключения, то есть его класс. По нему сразу понятно, что за ошибка.
  • / by zero — сообщение с подробностями.
  • at Main.main(Main.java:6) — трассировка стека (stack trace): где именно возникла ошибка. Здесь — в методе main, строка 6.

Если ошибка случилась глубоко внутри вызовов, строк at будет несколько. Самая верхняя — место, где исключение возникло, ниже — кто вызвал этот код.

int divide(int a, int b) {
    return a / b;
}
 
void main() {
    IO.println(divide(10, 0));
}

Результат:

Exception in thread "main" java.lang.ArithmeticException: / by zero
	at Main.divide(Main.java:2)
	at Main.main(Main.java:6)

Частые исключения

С этими исключениями новички сталкиваются чаще всего:

ИсключениеКогда возникает
ArithmeticExceptionцелочисленное деление на ноль
ArrayIndexOutOfBoundsExceptionиндекс за пределами массива
NullPointerExceptionвызов метода у null
NumberFormatExceptionстроку не удалось превратить в число
IllegalArgumentExceptionметоду передали недопустимый аргумент

Например, Integer.parseInt не поймёт буквы:

void main() {
    int age = Integer.parseInt("двадцать");
}

Результат:

Exception in thread "main" java.lang.NumberFormatException: For input string: "двадцать"
	at Main.main(Main.java:2)

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

Все исключения — объекты классов, унаследованных от Throwable. У него две ветви:

  • Error — серьёзные сбои самой виртуальной машины, например нехватка памяти (OutOfMemoryError). Их обычно не обрабатывают. Откуда берутся такие сбои, рассказано в уроке Память и сборка мусора.
  • Exception — ошибки, с которыми программа может справиться. Его подкласс RuntimeException объединяет ошибки в логике кода: деление на ноль, null, неверный индекс.

Как это деление влияет на код, разберём в уроке о проверяемых и непроверяемых исключениях.

Исключение — тоже объект

Раз исключение — объект, у него есть методы. getMessage() возвращает сообщение, а getClass().getSimpleName() — короткое имя класса. Чтобы получить объект исключения, его нужно перехватить конструкцией try-catch — ей посвящён следующий урок:

void main() {
    try {
        int[] scores = {5, 4, 3};
        IO.println(scores[3]);
    } catch (ArrayIndexOutOfBoundsException e) {
        IO.println(e.getClass().getSimpleName());
        IO.println(e.getMessage());
    }
}

Результат:

ArrayIndexOutOfBoundsException
Index 3 out of bounds for length 3

Частая ошибка

Самое частое исключение в Java — NullPointerException: метод вызывают у значения null, то есть у «ничего». Например, метод вернул null, а результат сразу использовали:

String findName() {
    return null;
}
 
void main() {
    IO.println(findName().length());
}

Результат:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because the return value of "Main.findName()" is null
	at Main.main(Main.java:6)

Современная Java подробно объясняет, что именно оказалось null: здесь — результат метода findName(). Прежде чем вызывать методы у значения, которое может отсутствовать, проверяйте его (if (name != null)) или возвращайте из метода Optional.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.