Encodera

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

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

Оглавление

try, catch и finally

Исключение не обязательно должно ронять программу. Его можно перехватить (catch) и решить, что делать дальше: показать понятное сообщение, взять значение по умолчанию, попробовать ещё раз. Для этого служит конструкция try-catch.

try и catch

Код, который может выбросить исключение, помещают в блок try. Следом идёт блок catch с типом исключения, которое нужно перехватить:

void main() {
    try {
        int result = 10 / 0;
        IO.println(result);
    } catch (ArithmeticException e) {
        IO.println("Делить на ноль нельзя");
    }
    IO.println("Программа продолжает работу");
}

Результат:

Делить на ноль нельзя
Программа продолжает работу

Когда в try возникает исключение, остаток блока пропускается и управление переходит в подходящий catch. После него программа идёт дальше как обычно. Если исключения не было, catch не выполняется вовсе.

Объект исключения

В скобках catch объявляется переменная — обычно её называют e. Через неё доступно сообщение об ошибке:

void main() {
    String input = "12a";
    try {
        int number = Integer.parseInt(input);
        IO.println(number * 2);
    } catch (NumberFormatException e) {
        IO.println("Ошибка: " + e.getMessage());
    }
}

Результат:

Ошибка: For input string: "12a"

Несколько catch

Один try может иметь несколько блоков catch — для разных ошибок разная реакция. Java проверяет их сверху вниз и выполняет первый подходящий. Если реакция одинаковая, типы можно перечислить через | в одном блоке: catch (NumberFormatException | ArithmeticException e) — это называется multi-catch.

void check(String text, int index) {
    try {
        int value = Integer.parseInt(text);
        int[] data = new int[3];
        data[index] = value;
        IO.println("Записано: " + value);
    } catch (NumberFormatException e) {
        IO.println("Не число: " + text);
    } catch (ArrayIndexOutOfBoundsException e) {
        IO.println("Плохой индекс: " + index);
    }
}
 
void main() {
    check("7", 1);
    check("семь", 1);
    check("7", 5);
}

Результат:

Записано: 7
Не число: семь
Плохой индекс: 5

finally

Блок finally выполняется всегда: было исключение или нет, перехватили его или нет. В нём обычно освобождают ресурсы — закрывают файлы и соединения:

void main() {
    try {
        IO.println("Открываем соединение");
        int x = 5 / 0;
    } catch (ArithmeticException e) {
        IO.println("Ошибка: " + e.getMessage());
    } finally {
        IO.println("Закрываем соединение");
    }
}

Результат:

Открываем соединение
Ошибка: / by zero
Закрываем соединение

Для закрытия ресурсов есть и более удобный способ — try-with-resources, ему посвящён отдельный урок.

throw

Исключения можно выбрасывать и самому — оператором throw. Так метод сообщает, что получил недопустимые данные:

void setAge(int age) {
    if (age < 0) {
        throw new IllegalArgumentException("Возраст не может быть отрицательным: " + age);
    }
    IO.println("Возраст: " + age);
}
 
void main() {
    setAge(30);
    try {
        setAge(-5);
    } catch (IllegalArgumentException e) {
        IO.println(e.getMessage());
    }
}

Результат:

Возраст: 30
Возраст не может быть отрицательным: -5

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

Блоки catch проверяются по порядку, поэтому общий тип нельзя ставить раньше частного. Exception перехватывает и ArithmeticException, и второй блок никогда бы не выполнился — компилятор считает это ошибкой:

void main() {
    try {
        int x = 10 / 0;
    } catch (Exception e) {
        IO.println("Что-то пошло не так");
    } catch (ArithmeticException e) {
        IO.println("Деление на ноль");
    }
}

Результат:

Main.java:6: error: exception ArithmeticException has already been caught
    } catch (ArithmeticException e) {
      ^
1 error
error: compilation failed

Ставьте частные исключения выше общих. И не злоупотребляйте catch (Exception e): лучше перехватывать только те ошибки, которые вы действительно умеете обработать.

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

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