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

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

Открыта

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-finally — try-finally. Выглядит это примерно так:

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

Комментарии (253)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Euraks Backend Developer
1 октября, 09:31
на finally надейся но сам не плошай. Не прям уж всегда он выполниться, если выше случится Error например
Grigoryvvv
Уровень 28
Expert
15 марта, 15:55
15.03.2026 / 15 уровень
Valery
Уровень 1
11 марта, 19:25
Еще один более современный подход 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.
Уровень 1
11 июня, 20:24
круто, но думаю, что у авторов не было цели объяснить работу со стримами, а принцип работы именно try-catch-finally и закрытие стрима - отличный этому пример
Anonymous #3585174
Уровень 33
8 июля 2025, 07:02
like
Юрий Frontend Developer
24 февраля 2025, 11:41
try { Жили-были у деда; Гуси людоеды; catch(ExceptionEat e) { System.out.println(e); }
Andrey Ku
Уровень 2
Expert
20 января 2025, 18:13
Зачем нужно throw? Передача исключения дальше: Если программа не может обработать исключение полностью, оно передаётся на уровень вызова метода, чтобы обработка произошла выше по стеку вызовов. Прозрачность ошибок: Исключение остаётся доступным для других обработчиков. Например, если этот метод используется в другой части программы, вызывающий код узнает, что что-то пошло не так.
20 ноября 2024, 07:37
Кото-то может подсказать по задаче со слоном, почему предыдущие ответы выводятся в консоли в обратном порядкем если снова выбросить искючение?
CodeMashineРаботает в Автосервис
20 ноября 2024, 18:17
это ты сам реализовать должен. Сначала записать ответы куда нибудь , потом вывести в обратном порядке.
Олеся
Уровень 18
5 декабря 2024, 12:49
Это все из-за рекурсивного вызова функции (это когда функция вызывает саму себя). Обратный порядок вывода ответов связан с способом хранения цепочки вызовов функций в памяти компьютера. Когда одна функция вызывает внутри себя другую функцию, то контекст (ссылка на функцию, ее переменные) "верхней" функции сохраняется в стэк вызовов. Стэк - это структура хранения объектов, организованная по принципу 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, 19:43
нет бро, это рекурсия
Anonymous #3438559
Уровень 4
24 декабря 2024, 19:23
спасибо за отличное объяснение. прошу ответить на уточняющий вопрос, в коде два вызова метода buyElephant, первый из main - buyElephant(null, scanner);, а второй изнутри - buyElephant(answer, scanner);. для чего это сделано? первый вызов запускает рекурсию или они по очереди работают?
VictorThe main expert in Automa в Строительная компани
29 января 2025, 08:25
Я думаю первый вызов с null - типа завязать разговор (аналогия - задание для переменной начального значения при объявлении, хотя дальше это значение может в программе вообще не появляться)
Виктор
Уровень 28
28 июня 2025, 18:12
Все́ понятно, спасибо.
Denis Nkn
Уровень 26
7 марта, 19:14
Может я что-то не так написал, но у меня просто по скрипту программа отрабатывает, не печатая предыдущие ответы, хотя в правильном решении написано так же, как и у меня
Ринат
Уровень 22
20 ноября 2024, 06:56
Как я понял try-catch-throw-finally Если к примеру мы в коде не проработали какую то логику которая может привести к ошибке и программа по этому экстренно завершается. То надо бы, что ты наша программа не просто завершилась, но и "убиралась" за собой. Если программа контактирует с внешними ресурсами. закрыла открытые файлы, сохранила или наоборот не сохраняла изменения. Или сделала резервную копию. Там наверно еще много что надо бы обязательно сделать, но я пока этого не знаю.
w5277c
Уровень 32
4 декабря 2024, 01:57
Такие процессы, как закрытие файла при завершении программы - задача операционки. Именно она подчищает все ресурсы использованные программой, если программа сама этого не сделала.
3 ноября 2024, 15:02
гайс а зачем нам вообще throw-ить ошибку? или например создавать зачем нам новую ошибку зачем например? не очень понимаю смысла в этих действиях, буду рад если кто нибуть пояснит заранее спасибо
Gralexx
Уровень 19
13 ноября 2024, 17:56
Согласен с вами! Из лекции не понятно зачем нам перехватывать исключение, чтобы потом опять его выбрасывать. Оператор throw, на мой взгляд новичка, объяснили ужасно.
Ринат
Уровень 22
20 ноября 2024, 06:41
Программа без try - catch^ Работает и если где то в коде есть ошибка компиляции - выбрасывает исключение, работа программы завершается и в консоль пишутся красные непонятные с первого раза слова. Которые объясняют что и где произошло. Если мы код где произошла ошибка обернем в try-catch. Программа поймет что мы знаем об этой ошибке и не будет останавливать работу программы, просто выполнит блок catch и дальше будет работать как не в чем небывало. throw-ить ошибку же надо для того, что бы программа после выполнения блока catch (в котором можно к примеру вывести в консоль "Тебе же написали вводи цифры, а не буквы") снова выбрасывало исключение, работа программы завершалась и в консоль летят красные непонятные слова. Которые объясняют что и где произошло.
Артём К
Уровень 32
22 января 2025, 13:07
спасибо добрый человек
VictorThe main expert in Automa в Строительная компани
29 января 2025, 08:31
Что бы пользователь не пугался - выводим объявление - это обычной сбой, мол для бета версии обычное дело - всё под контролем. Ну дальше маска смерти............всё как обычно.
NightCrowSystem Engineer в Аплана
27 сентября 2024, 12:40
Блин, а про Слона можно было дать хоть какие то пояснения? Я конечно догадываюсь, что при возникновении ошибки вываливается кэш, который копиться пока мы варимся внутри метода, вызывая его из себя же. Но это только мои догадки....
Ilya Klimchev Backend Developer
30 октября 2024, 15:31
Не усложняйте) Рекурсивный вызов метода - это точно то же самое, что и вызов любого другого метода. Вас же не смущает, что в цепочке вызовов от main() до, например, System.out.println() могут быть сотни и тысячи методов? В памяти, при этом хранится контекст всех этих методов...и не только ;)