Винятками чи винятковими ситуаціями (станами) називаються помилки, що виникли у програмі під час її роботи. Усі винятки Java є об'єктами. Тому можуть породжуватися як автоматично у разі виняткової ситуації, а й створюватися самим розробником. Ієрархія класів винятків: Винятки поділяються на кілька класів, але вони мають загального предка - клас
Throwable
. Його нащадками є Exception
підкласи Error
. Винятки ( Exceptions
) є результатом проблем у програмі, які в принципі вирішуються та передбачувані. Наприклад, стався поділ на нуль у цілих числах. Помилки (Errors
) являють собою серйозніші проблеми, які, згідно специфікації Java, не слід намагатися обробляти у власній програмі, оскільки вони пов'язані з проблемами рівня JVM. Наприклад, винятки такого роду виникають, якщо закінчилася пам'ять, доступна віртуальній машині. Програма додаткову пам'ять все одно не зможе забезпечити для JVM. У Java всі винятки поділяються на три типи: контрольовані винятки ( checked
) і неконтрольовані винятки ( unchecked
), до яких належать помилки ( Errors
) та виключення часу виконання ( RuntimeExceptions
, нащадок класу Exception
). Контрольовані винятки є помилками, які можна і потрібно обробляти в програмі, до цього типу відносяться всі нащадки класу Exception
(але неRuntimeException
). Обробка виключення може бути здійснена за допомогою операторів try…catch
або передана зовнішній частині програми. Наприклад, метод може передавати виключення, що виникли в ньому, вище за ієрархією викликів, сам його не обробляючи. Неконтрольовані винятки не вимагають обов'язкової обробки, проте, за бажання, можна обробляти винятки класу RuntimeException
. Відкомпілюємо та запустимо таку програму:
class Main {
public static void main(String[] args) {
int a = 4;
System.out.println(a/0);
}
}
У момент запуску на консоль буде виведено таке повідомлення:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.main(Main.java:4)
З повідомлення видно клас виключення, що сталося - ArithmeticException
. Цей виняток можна обробити:
class Main {
public static void main(String[] args) {
int a = 4;
try {
System.out.println(a/0);
} catch (ArithmeticException e) {
System.out.println("Произошла недопустимая арифметическая операция");
}
}
}
Тепер замість стандартного повідомлення про помилку буде виконуватися блок catch
, параметром якого є об'єкт e відповідного виключення класу (самому об'єкту можна давати будь-яке ім'я, воно знадобиться в тому випадку, якщо ми побажаємо знову примусово викинути цей виняток, наприклад, щоб він був перевірений якимось ще обробником). У блок try
при цьому поміщається фрагмент програми, де потенційно може виникнути виняток. Одному try
може відповідати відразу кілька блоків catch із різними класами винятків.
import java.util.Scanner;
class Main {
public static void main(String[] args) {
int[] m = {-1,0,1};
Scanner sc = new Scanner(System.in);
try {
int a = sc.nextInt();
m[a] = 4/a;
System.out.println(m[a]);
} catch (ArithmeticException e) {
System.out.println("Произошла недопустимая арифметическая операция");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Обращение по недопустимому индексу массива");
}
}
}
Якщо запустивши представлену програму, користувач введеться з клавіатури 1 або 2, програма відпрацює без створення будь-яких винятків. Якщо користувач введе 0, то виникне виняток класу ArithmeticException
і воно буде оброблено першим блоком catch
. Якщо користувач введе 3, то виникне виняток класу ArrayIndexOutOfBoundsException
(вихід за межі масиву), і воно буде оброблено другим блоком catch
. Якщо користувач введе неціле число, наприклад, 3.14, то виникне виняток класу InputMismatchException
(невідповідність типу значення, що вводиться), і воно буде викинуто у форматі стандартної помилки, оскільки його ми ніяк не обробляли. Проте можна додати обробник для класуException
, оскільки цей клас батьківський всім інших контрольованих винятків, він перехоплюватиме будь-які їх (зокрема, і InputMismatchException
).
import java.util.Scanner;
class Main {
public static void main(String[] args) {
int[] m = {-1,0,1};
int a = 1;
Scanner sc = new Scanner(System.in);
try {
a = sc.nextInt();
m[a-1] = 4/a;
System.out.println(m[a]);
} catch (ArithmeticException e) {
System.out.println("Произошла недопустимая арифметическая операция");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Обращение по недопустимому индексу массива");
} catch (Exception e) {
System.out.println("Произошло ещё якое-то исключение");
}
}
}
Оскільки винятки побудовані на ієрархії класів і підкласів, спочатку треба намагатися обробити більш приватні винятки і лише потім більш загальні. Тобто поставивши першим (а не третім) блок з обробкою виключення класу Exception
, ми б ніколи не побачабо жодних повідомлень про помилку, окрім «Сталося ще якесь виключення» (всі винятки перехопабося б відразу цим блоком і не доходабо до решти). Необов'язковим додаванням до блоків try…catch
може бути блок finally
. Вміщені в нього команди виконуватимуться у будь-якому випадку, незалежно від того, чи відбулося виключення чи ні. При тому, що при виникненні необробленого виключення частина програми, що залишилася після генерації цього виключення, — не виконується. Наприклад, якщо виняток виник у процесі якихось тривалих обчислень, у блоціfinally
Ви можете показати або зберегти проміжні результати. Посилання на першоджерело: Винятки та їх обробка
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ