JavaRush/Курси/Java Syntax Zero/Викидання винятків

Викидання винятків

Відкрита

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 Zero,  15 рівень,  3 лекція
Недоступна
Купи слона
Купи слона

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
{
   код, який потрібно виконати в будь-якому разі
}

15
Задача
Java Syntax Zero,  15 рівень,  3 лекція
Недоступна
Їжа їжею, а сон за розкладом
Їжа їжею, а сон за розкладом
Коментарі (11)
  • популярні
  • нові
  • старі
Щоб залишити коментар, потрібно ввійти в систему
16 червня 2023, 20:32
Не зрозумів як ми в другій задачі запам'ятовуємо ВСІ попередні відповіді. Адже ми на кожному виклику перезаписуємо змінну answer(після if-else). Задачу я розв'язав, але цікаво зрозуміти як працює код(а це важко). Поясніть будь ласка.
Костянтин
Рівень 58
Expert
21 червня 2023, 10:59
Теж спочатку не зрозумів. Але трохи подумавши дійшов таких висновків. По перше в нас відбувається рекурсивний виклик методу buyElephant(), коли ми в блоці try знову викликаємо цей метод. І коли ми вводимо відповідь "ок", то ми створюємо виключення, яке обробляємо, виводимо на консоль answer і кидаємо виключення далі. Якби ми не кидали виключення, то просто би вивели "ок" і программа зупинилася. але через те що виключення кидається далі ми починаємо підніматися угору ланцюгом викликів методів доки не дійдемо до main. Але так як єдиний метод який ми викликали був buyElephant(), то і обробка виключення залишається та сама і виключення кидається далі, тому ми отримуємо вивід answer, але в зворотньому порядку, і тільки коли ми доходимо до main, то отримуємо помилку, бо в main нема обробки виключення і виводиться весь ланцюжок наших викликів через які ми прокинули наше виключення. А різні значення answer зберігаються скоріше за все в stackTrace, який зберігає всі наші виклики методів і тому вони виводяться в зворотньому порядку. Сподіваюсь зрозуміло пояснив. P.S. Поки зрозумів, що "ок" написано кирилицею, думав з глузду з'їду.
21 червня 2023, 15:33
Дякую, зрозумів. Тоді це було складно бо треба було спочатку прочитати подальші лекції про стек викликів методів
Elder_HD Працює в UPCExpert
27 травня 2023, 22:26
Не зовсім зрозумів для чого блок finally (в яких випадках може бути корисним). Адже в лекції закрити файл можна наступним чином:
catch(Exception except)
{
   System.out.println("Перехопили виняток");
   if (source != null)
       source.close();
   throw except;
}
Або ж в задачі вивід рядка "ліг спати голодним" можна було б додати в блок catch (разом із завершенням методу через return, або throw exception). Так, я розумію, що Finally корисний тим, що спрощує код (і його прочитанність), але все ж хотілося б побачити більш яскраві приклади у лекції
Pavlo Kezin
Рівень 23
16 вересня 2023, 15:02
теж про це думав. що можно досягнути того самого просто прибравши "повернення".
Oleksii Ananiev
Рівень 16
10 грудня 2025, 19:14
Цікаво, чи через два роки у Вас з'явилась відповідь на це питання?) Бо Ваш коментар змусив мене задуматись, але наскільки я розумію, то в коді
catch(Exception except)
{
   System.out.println("Перехопили виняток");
   if (source != null)
       source.close();
   throw except;
}
файл закриється тільки у випадку, коли програма зловила ексепшен. А якщо ексепшена нема? Файл не закриється
Avis_arctica
Рівень 36
4 липня 2022, 12:40
Задачки вирішила, але тему до кінця не зрозуміла, особливо цю частину коду: Навіщо ми викидаємо виняток повторно у блоці catch? catch(Exception except) { System.out.println("Перехопили виняток"); throw except; }
hidden #3143523
Рівень 25
5 грудня 2022, 07:11
ну а може в наступному блоці тобі знадобиться цей же виняток .Але без повторного виклику винятку його просто забере перший catch
Roma Chernesh
Рівень 16
16 лютого 2023, 20:02
cяби! бо так би для мене tbrow залишилося б загадкою:)
Pavlo Kezin
Рівень 23
16 вересня 2023, 15:11
наскільки я зрозумів. Наприклад. Якщо число повинно бути цілим і додатним. І catch 1 повинен ловити, що число не від'ємне, а catch 2, що число ціле, ТО... без throw ми так і не дізнаємося, що помилки дві, а не одна, якщо введемо -1,5 оскільки спрацює тільки перший catch. Хоча умови обох підходять. Хтось може підтвердити мої здогадки?
Максим
Рівень 49
19 серпня 2024, 15:00
В лекції є чітко вказано - "Повторно кинутий виняток не може бути захоплено іншими блоками catch цього самого try-блока." Тому не зрозуміло, що тут хотіли показати цим прикладом. Тема дуже важлива, але підготували її дуже поверхнево, як то кажуть, багато води.