Throw и throws
Throw: создать исключительную ситуацию вручную
Исключение не обязательно должно возникнуть само из-за деления на ноль или неверного индекса.
Код может явно сообщить, что продолжать обычное выполнение нельзя.
Для этого используется оператор throw.
static void validateAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("age");
}
System.out.println("valid");
}
Выражение new IllegalArgumentException("age") создаёт объект исключения,
а throw запускает его как исключительную ситуацию.
Если age отрицательный, строка с valid в этом вызове метода уже не выполнится.
После throw обычное выполнение прерывается
Как только выполняется throw, Java прекращает обычное выполнение текущего участка кода
и ищет подходящий обработчик. Уже знакомый catch может перехватить выброшенный объект,
если его тип подходит обработчику.
try {
validateAge(-5);
System.out.println("after call");
} catch (IllegalArgumentException e) {
System.out.println("caught");
}
System.out.println("done");
Вызов validateAge(-5) приводит к throw,
поэтому after call не выводится. Управление переходит в catch,
а после него программа продолжает работу и выводит done.
Throws описывает, что исключение может выйти из метода
Ключевое слово throws записывается в объявлении метода после списка параметров.
Оно показывает, что исключение указанного типа может покинуть метод и перейти к вызывающему коду.
static void checkAccess(boolean allowed) throws Exception {
if (!allowed) {
throw new Exception("denied");
}
}
Здесь throw выполняется внутри тела метода и действительно выбрасывает объект исключения,
а throws Exception находится в сигнатуре и описывает возможность выхода этого исключения наружу.
Сам по себе throws ничего не выбрасывает и не обрабатывает.
throw и throws решают разные задачи.
throw — это действие внутри кода: выбросить конкретный объект исключения.
throws — часть объявления метода: указать тип исключения, которое может выйти из него.
Исключение может пройти через несколько вызовов
Метод не обязан обрабатывать исключение в том же месте, где оно возникло.
Если подходящего catch внутри метода нет, исключение может перейти к вызывающему коду,
где его уже можно обработать.
static void open() throws Exception {
checkAccess(false);
}
try {
open();
} catch (Exception e) {
System.out.println("caught");
}
В этом примере исключение создаётся и выбрасывается в checkAccess(),
проходит через open() и перехватывается внешним catch.
Так throw, throws и уже знакомый catch
работают вместе: исключение возникает в одном месте, может быть передано выше и обработано там, где это предусмотрено кодом.