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

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

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

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.



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
{
   код, который нужно выполнить в любом случае
}

Комментарии (253)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Grigoryvvv Уровень 17 Expert
15 марта 2026
15.03.2026 / 15 уровень
Valery Уровень 4
11 марта 2026
Еще один более современный подход try-catch-finally, это try-with-resources, который здесь не описали, хотя вкраце могли и очень полезно ! Переделанный код из лекции:

try (var source = new FileInputStream("c:\\note.txt")) {
    source.read();
} catch (Exception except) {
    System.out.println("Перехватили исключение");
    throw except;
}
В лекции говорится о закрытии потока записи файла в блоке finally, который мы открыли в блоке try, но при подходе try-with-resources можно не думать о закрытии потока, так как конструкция закроет его сама автоматически. Даже те, о которых мы можем не знать или не помнить в более серьезной программе. Подробнее можно почитать тут: https://javarush.com/groups/posts/isklyucheniya-java
Bogdan K. Уровень 26
11 июня 2026
круто, но думаю, что у авторов не было цели объяснить работу со стримами, а принцип работы именно try-catch-finally и закрытие стрима - отличный этому пример
Anonymous #3585174 Уровень 33
8 июля 2025
like
Юрий Уровень 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 Уровень 4
24 декабря 2024
спасибо за отличное объяснение. прошу ответить на уточняющий вопрос, в коде два вызова метода buyElephant, первый из main - buyElephant(null, scanner);, а второй изнутри - buyElephant(answer, scanner);. для чего это сделано? первый вызов запускает рекурсию или они по очереди работают?
Victor Уровень 21
29 января 2025
Я думаю первый вызов с null - типа завязать разговор (аналогия - задание для переменной начального значения при объявлении, хотя дальше это значение может в программе вообще не появляться)
Виктор Уровень 28
28 июня 2025
Все́ понятно, спасибо.
Denis Nkn Уровень 23
7 марта 2026
Может я что-то не так написал, но у меня просто по скрипту программа отрабатывает, не печатая предыдущие ответы, хотя в правильном решении написано так же, как и у меня
Ринат Уровень 22
20 ноября 2024
Как я понял try-catch-throw-finally Если к примеру мы в коде не проработали какую то логику которая может привести к ошибке и программа по этому экстренно завершается. То надо бы, что ты наша программа не просто завершилась, но и "убиралась" за собой. Если программа контактирует с внешними ресурсами. закрыла открытые файлы, сохранила или наоборот не сохраняла изменения. Или сделала резервную копию. Там наверно еще много что надо бы обязательно сделать, но я пока этого не знаю.
w5277c Уровень 32
4 декабря 2024
Такие процессы, как закрытие файла при завершении программы - задача операционки. Именно она подчищает все ресурсы использованные программой, если программа сама этого не сделала.
Максим Антонов Уровень 27
3 ноября 2024
гайс а зачем нам вообще throw-ить ошибку? или например создавать зачем нам новую ошибку зачем например? не очень понимаю смысла в этих действиях, буду рад если кто нибуть пояснит заранее спасибо
Gralexx Уровень 19
13 ноября 2024
Согласен с вами! Из лекции не понятно зачем нам перехватывать исключение, чтобы потом опять его выбрасывать. Оператор throw, на мой взгляд новичка, объяснили ужасно.
Ринат Уровень 22
20 ноября 2024
Программа без try - catch^ Работает и если где то в коде есть ошибка компиляции - выбрасывает исключение, работа программы завершается и в консоль пишутся красные непонятные с первого раза слова. Которые объясняют что и где произошло. Если мы код где произошла ошибка обернем в try-catch. Программа поймет что мы знаем об этой ошибке и не будет останавливать работу программы, просто выполнит блок catch и дальше будет работать как не в чем небывало. throw-ить ошибку же надо для того, что бы программа после выполнения блока catch (в котором можно к примеру вывести в консоль "Тебе же написали вводи цифры, а не буквы") снова выбрасывало исключение, работа программы завершалась и в консоль летят красные непонятные слова. Которые объясняют что и где произошло.
Артём К Уровень 32
22 января 2025
спасибо добрый человек
Victor Уровень 21
29 января 2025
Что бы пользователь не пугался - выводим объявление - это обычной сбой, мол для бета версии обычное дело - всё под контролем. Ну дальше маска смерти............всё как обычно.
NightCrow Уровень 27
27 сентября 2024
Блин, а про Слона можно было дать хоть какие то пояснения? Я конечно догадываюсь, что при возникновении ошибки вываливается кэш, который копиться пока мы варимся внутри метода, вызывая его из себя же. Но это только мои догадки....
Ilya Klimchev Уровень 2
30 октября 2024
Не усложняйте) Рекурсивный вызов метода - это точно то же самое, что и вызов любого другого метода. Вас же не смущает, что в цепочке вызовов от main() до, например, System.out.println() могут быть сотни и тысячи методов? В памяти, при этом хранится контекст всех этих методов...и не только ;)
Sergo Уровень 22
2 сентября 2024