Винятки в Java

Як відомо, винятки – це події, що виникають при виконанні програми. Ці події порушують нормальний хід речей.

Блок try, блок catch

Частина коду, де можливе виникнення виняткової ситуації, що охоплюють блоком try. Обробники винятків оголошуються в блоці catch, який слід відразу за блоком try. Блоків catch може бути кілька для одного блоку try. У блоці catch відбувається обробка винятку, а його аргумент вказує тип винятку, який може обробити даний блок, тобто тип аргументу є тип винятку. Код, записаний у блоці catch є обробник винятку.

Блок finally

Після блоку(ів) ислючения може розташовуватися блок finally. Прийнятний випадок, коли немає блоків catch, але є блок finally. Код блоку finally виконується завжди, а не тільки при виникненні виключення. У ньому можна виконувати обов'язкові завершальні дії, очищення, наприклад, закрити потік, а не в блоці try. Після finally виконання програми продовжується з наступного рядка коду.

Схематично все виглядає так:

а може бути без блоків catch, ось так:

або без блоку, нарешті:

Розглянемо докладніше, що відбувається при виникненні виняткової ситуації.

При виникненні виняткової ситуації, формується об'єкт виключення, що містить інформацію про це виключення, який передається системі. У таких випадках кажуть, що соотвестсвующая частина програми викидає виключення, тобто формує об'єкт виключення і передає його системі. Далі починається робота системи, але перш ніж ми її розберемо, треба зрозуміти що таке стек викликів.

Вгору

   Врізка

Стек викликів(call stack)

Стек викликів(call stack) - це пследовательность викликів методів, починаючи від методу main до цікавить нас методу. Розглянемо умовний приклад. Є клас:

Тут стек викликів такий: main викликає метод methoda(), метод methoda() викликає метод " (), метод() викликає стирання тому().

   Кінець врізки

Продовжимо вивчення дій системи після отримання нею об'єкта виключення (припустимо, що тип об'єкта виключення - AnException), викинутого якимось методом. Нехай це буде метод стирання тому(), див. врізку «Стек викликів» вище. Система починає переглядати стек викликів для стирання тому() у зворотному порядку, тобто, стартуючи з самого методу стирання тому(), переміщується в напралении головне. Мета цього перегляду знайти обробник винятку, що виник у стирання тому(). Спочатку система переглядає стирання тому(), якщо в ньому немає потрібного обробника виключення, то переходить до метод " (с), якщо і в ньому немає, то переходить до метод methoda(). метод methoda() містить обробник типу AnException, ось цього-то обробникові і система передає об'єкт виключення на обробку. Кажуть, що обробник захоплює (catch) виняток. Якщо система не знайшла б обробник ислючения потрібного типу, то виконання програми було б завершено.

Якщо б у методу methoda() було кілька блоків catch, то система вибрала б перший відповідний блок, тобто такий блок, тип аргумент якої співпадає з типом виключення.

Вгору

Три категорії винятків

Є три категорії винятків:

Контрольовані (перевірено) виключення. Наприклад, помилки введення. Такі винятку рекомендується обробляти;

Помилка (помилка). Це винятку, викликані зовнішніми, по відношенню до програму, причинами і програму їх, як правило, не обробляє. Такі винятки визначаються класом помилка або його підкласами;

Винятку часу виконання (runtime exception). Наприклад, помилки в коді. Такі винятки визначаються класом RuntimeException або його підкласами. Ці винятки можуть оброблятися.

Виключення другого і третього типу називають неконтрольовані (незареєстрований) виключення.

Метод може не обробляти виняток, але, припускаючи, що воно може виникнути, передати його на обробку в стек викликів. Тоді в оголошенні методу пишуть оператор кидки: і в ньому через кому перелік можливих типів виключень. Приклад:

Метод може сам викинути виняток. Для цього використовують оператор throw і об'єкт-винятку в ньому. Приклад:

Якщо цьому прикладі a < 10, то буде викинуто виняток AnException, так, як якщо б тут відбулася відповідна помилка.

Викинути виняток оператором throw можна і з тіла оработчика іншого виключення. Так виникає ланцюжок винятків (прикутий виключення). Приклад:

Всі класи винятків сходять до класу Throwable. Безпосередніми спадкоємцями його є класи помилка і виняток. Від виняток відбуваються RuntimeException і всі класи контрольованих винятків.

Ми вже знаємо, що виключення типу помилка обробляє система, зазвичай не торкаємося.

Винятки типу RuntimeException говорять про помилки в коді. Такі винятки можуть оброблятися, але краще просто виправити помилки коду.

Винятки типу виняток говорять про наявність проблем, але вони не є серйозними системними. Такі помилки слід обробляти.

Можна створювати свої класи винятків як прямих чи ні наследков виняток. Прийнято до назв таких класів додавати слово виняток.

Якщо тип аргументу оператора catch виняток, то соотвестсвующий обробник виключень зможе захопити всі контрольовані вилучення і винятки типу RuntimeException. Так можна вчинити, якщо немає особливих вимог до обробника або якщо можуть виникнути непередбачені виключення. Але якщо потрібен особливий підхід, то краще використовувати спадкоємців виняток.

Вгору

Як самому створити клас винятку?

Так як ми повинні обробляти контрольовані виключення, то успадкуємо наш клас від виняток.


Вгору

Приклад

У висновку наводжу повний код прикладу, який розглядався на протязі цього розділу. Головний клас:

Клас винятку AnException:

Клас винятку NextException: