JavaRush /Курсы /Java Syntax Pro /Выбрасывание исключений

Выбрасывание исключений

Java Syntax Pro
15 уровень , 3 лекция
Открыта

1. Оператор throw

Исключение, пока оно не выброшено в систему, или когда оно уже перехвачено блоком catch — это в принципе просто объект класса, унаследованного от Exception (вернее, от Throwable). Никакими магическими особенностями сам объект-исключение не обладает.

Вся логика работы исключений — это просто особый сценарий поведения Java-машины, когда в ее среду выполнения вброшено исключение.

Вы всегда можете снова вбросить Java-машине исключение, которое только что перехватили. Для этого нужно использовать оператор throw:

throw исключение;

Пример:

Код Вывод на экран
try
{
   int d = 2/0;
}
catch(Exception except)
{
   System.out.println("Перехватили исключение");
   throw except;
}
Перехватили исключение

В этом коде мы перехватили исключение, вывели на экран надпись об этом и снова выбросили его.

Повторно выброшенное исключение не может быть захвачено другими блоками catch этого же try-блока.


2. Свое исключение

Кстати, вы можете сами создать объект-исключение: это просто объект типа Exception или унаследованного от него класса. И выбросить его.

Это проще, чем кажется. Пример:

Код Вывод на экран
try
{
   throw new RuntimeException();
}
catch(Exception except)
{
   System.out.println("Перехватили исключение");
   throw except;
}
Перехватили исключение

В примере выше мы создали новый объект-исключение типа RuntimeException и тут же выбросили его с помощью оператора throw.

Оно будет сразу захвачено блоком catch, т.к. тип RuntimeException унаследован от типа Exception. Код catch(Exception except) захватывает объекты-исключения всех классов, унаследованных от класса Exception.


15
Задача
Java Syntax Pro, 15 уровень, 3 лекция
Недоступна
Купи слона
Разберись, что делает программа. В блоке catch выведи на экран переменную answer и брось дальше пойманное исключение.

3. Ключевое слово finally

Еще один важный момент. Иногда программисту нужно сделать некоторые действия независимо от того, было исключение в коде или нет. Например, в коде мы открыли файл на запись, а открытый файл нужно обязательно закрыть вызовом метода close().

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

Для выполнения таких обязательных действий к оператору try-catch добавили еще один блок — finally, и получился оператор try-catch-finally. Выглядит это дело примерно так:

Пример:

FileInputStream source = null;
try
{
   source = new FileInputStream("c:\\note.txt");
   source.read();
}
catch(Exception except)
{
   System.out.println("Перехватили исключение");
   throw except;
}
finally
{
   if (source != null)
      source.close();
}

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

Кстати, если вы не хотите перехватывать исключение, а блок finally вам нужен, используйте сокращенную запись блока try-catch-finallytry-finally. Выглядит это примерно так:

try
{
   код, где может возникнуть ошибка
}
finally
{
   код, который нужно выполнить в любом случае
}

15
Задача
Java Syntax Pro, 15 уровень, 3 лекция
Недоступна
Еда едой, а сон по расписанию
Запусти программу и посмотри, что происходит. В методе eat добавь блок finally, чтобы лев ложился спать, даже если ему не удалось перекусить. Ожидаемый вывод в случае, когда food != null: ищет еду нашел мясо все съел лег спать Ожидаемый вывод когда food == null: ищет еду ничего не нашел
Комментарии (247)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Юрий Уровень 20
24 февраля 2025
try { Жили-были у деда; Гуси людоеды; catch(ExceptionEat e) { System.out.println(e); }
Andrey Ku Уровень 2 Expert
20 января 2025
Зачем нужно throw? Передача исключения дальше: Если программа не может обработать исключение полностью, оно передаётся на уровень вызова метода, чтобы обработка произошла выше по стеку вызовов. Прозрачность ошибок: Исключение остаётся доступным для других обработчиков. Например, если этот метод используется в другой части программы, вызывающий код узнает, что что-то пошло не так.
20 ноября 2024
Кото-то может подсказать по задаче со слоном, почему предыдущие ответы выводятся в консоли в обратном порядкем если снова выбросить искючение?
CodeMashine Уровень 33
20 ноября 2024
это ты сам реализовать должен. Сначала записать ответы куда нибудь , потом вывести в обратном порядке.
Олеся Уровень 18
5 декабря 2024
Это все из-за рекурсивного вызова функции (это когда функция вызывает саму себя). Обратный порядок вывода ответов связан с способом хранения цепочки вызовов функций в памяти компьютера. Когда одна функция вызывает внутри себя другую функцию, то контекст (ссылка на функцию, ее переменные) "верхней" функции сохраняется в стэк вызовов. Стэк - это структура хранения объектов, организованная по принципу LIFO. Last In - First Out. Последний пришел - первый вышел. Стэк можно представить себе как стопку тарелок. Тарелки кладутся на самый верх стопки и забираются с самого верха. Применительно к коду будет выглядеть так: если функция A вызывает функцию B, а B вызывает C, то в стеке будет сохранен контекст в последовательности A-> B-> C. В данном примере C - верх стека, самая верхняя тарелка. Когда функция C завершается, из стека достается контекст следующей функции B и продолжается выполнение функции B с того места, где ее выполнение было прервано вызовом C. После завершения B, соответственно выполняется функция A. В случае задачи со слоном функция buyElephant вызывает саму себя раз за разом до тех пор, пока вы не введете "ок". Каждый такой вызов кладется в стек и у каждого вызова сохраняется контекст ( переменная answer в том числе). Как только вы вводите "ок" выбрасывается исключение и текущая функция завершается. Исполнение переходит к функции ниже по стэку, в ней мы это исключение ловим в блоке catch и выводим переменную answer в консоль. Объект исключения пробрасывается дальше, функция завершается, из стека достается следующий контекст функции, снова ловим исключение в блок catch, выводим переменную в консоль и снова пробрасываем исключение для отлова во внешнюю функцию. И таким образом до самого дна стэка.
Anonymous #3513637 Уровень 25
9 декабря 2024
нет бро, это рекурсия
Anonymous #3438559 Уровень 25
24 декабря 2024
спасибо за отличное объяснение. прошу ответить на уточняющий вопрос, в коде два вызова метода buyElephant, первый из main - buyElephant(null, scanner);, а второй изнутри - buyElephant(answer, scanner);. для чего это сделано? первый вызов запускает рекурсию или они по очереди работают?
Victor Уровень 29
29 января 2025
Я думаю первый вызов с null - типа завязать разговор (аналогия - задание для переменной начального значения при объявлении, хотя дальше это значение может в программе вообще не появляться)
Ринат Уровень 22
20 ноября 2024
Как я понял try-catch-throw-finally Если к примеру мы в коде не проработали какую то логику которая может привести к ошибке и программа по этому экстренно завершается. То надо бы, что ты наша программа не просто завершилась, но и "убиралась" за собой. Если программа контактирует с внешними ресурсами. закрыла открытые файлы, сохранила или наоборот не сохраняла изменения. Или сделала резервную копию. Там наверно еще много что надо бы обязательно сделать, но я пока этого не знаю.
w5277c Уровень 32
4 декабря 2024
Такие процессы, как закрытие файла при завершении программы - задача операционки. Именно она подчищает все ресурсы использованные программой, если программа сама этого не сделала.
Максим Антонов Уровень 25
3 ноября 2024
гайс а зачем нам вообще throw-ить ошибку? или например создавать зачем нам новую ошибку зачем например? не очень понимаю смысла в этих действиях, буду рад если кто нибуть пояснит заранее спасибо
Anonymous #3460895 Уровень 19
13 ноября 2024
Согласен с вами! Из лекции не понятно зачем нам перехватывать исключение, чтобы потом опять его выбрасывать. Оператор throw, на мой взгляд новичка, объяснили ужасно.
Ринат Уровень 22
20 ноября 2024
Программа без try - catch^ Работает и если где то в коде есть ошибка компиляции - выбрасывает исключение, работа программы завершается и в консоль пишутся красные непонятные с первого раза слова. Которые объясняют что и где произошло. Если мы код где произошла ошибка обернем в try-catch. Программа поймет что мы знаем об этой ошибке и не будет останавливать работу программы, просто выполнит блок catch и дальше будет работать как не в чем небывало. throw-ить ошибку же надо для того, что бы программа после выполнения блока catch (в котором можно к примеру вывести в консоль "Тебе же написали вводи цифры, а не буквы") снова выбрасывало исключение, работа программы завершалась и в консоль летят красные непонятные слова. Которые объясняют что и где произошло.
Артём К Уровень 32
22 января 2025
спасибо добрый человек
Victor Уровень 29
29 января 2025
Что бы пользователь не пугался - выводим объявление - это обычной сбой, мол для бета версии обычное дело - всё под контролем. Ну дальше маска смерти............всё как обычно.
NightCrow Уровень 27
27 сентября 2024
Блин, а про Слона можно было дать хоть какие то пояснения? Я конечно догадываюсь, что при возникновении ошибки вываливается кэш, который копиться пока мы варимся внутри метода, вызывая его из себя же. Но это только мои догадки....
Ilya Klimchev Уровень 24
30 октября 2024
Не усложняйте) Рекурсивный вызов метода - это точно то же самое, что и вызов любого другого метода. Вас же не смущает, что в цепочке вызовов от main() до, например, System.out.println() могут быть сотни и тысячи методов? В памяти, при этом хранится контекст всех этих методов...и не только ;)
Sergo Уровень 22
2 сентября 2024
VAKHANDER Уровень 32
12 августа 2024
У меня появился странный вопрос, то есть придумали инструмент чтобы запускать код, который не должен работать? То есть например программист не хотел заморачиваться с написанием четкого алгоритма, сделал обработку исключения при неправильной операции и программа запускается работает а программист дальше получает деньги и блек джек и все такое?????
Wren Уровень 29
12 августа 2024
Ну почему же? try - catch помогает при ситуациях, которые ну никак не могут находиться под контролем программиста. Например, идет работа с файлами. Может ли программист гарантировать, что файл вообще существует? Может ли он гарантировать, что у программы точно будет доступ к файлу? А вдруг, если потребуется создать файл и туда что-то записать, на диске будет не хватать памяти и система банально откажет в записи?
CoreOne Уровень 23 Expert
19 июля 2024
Исключения интересны) а вот про Енам что то скучновато было)
Мученик Уровень 15
28 мая 2024
Ну типа ничего сложного но сложна в понимание до сканального