Назад Зміст Вперед

9.3. Множинний catch

Кілька інструкцій catch після інструкції try

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

Щоб у програмі TryCatch.java перехоплювався також виняток типу ArithmeticException, достатньо після першої інструкції catch додати ще одну, в якій у параметрах буде вказуватися виняток типу ArithmeticException:
package inwe;

class TryCatch {
  ...
  try {
      // masuv[14] = 28;
      zminna = 1 / 0;
      System.out.println(В блоці try немає помилок!);
    }
    catch(IndexOutOfBoundsException vunjatok) { /* інструкція catch перехоплює об’єкт класу IndexOutOfBoundsException */
    /* Якщо даний об'єкт перехоплюється інструкцією сatch, то виводиться повідомлення про помилку та вміст об'єкту винятку */
      System.out.println(Помилка виконання програми:  + vunjatok);
    }
    catch(ArithmeticException vunjatok) { /* інструкція catch перехоплює об’єкт класу ArithmeticException */
    /* Якщо даний об'єкт перехоплюється інструкцією сatch, то виводиться повідомлення про помилку та вміст об'єкту винятку */
      System.out.println(Помилка виконання програми:  + vunjatok);
    }
  ...
}
В блоці try програмний код виконується до виникнення помилки, після чого виконання програми переходить до інструкцій catch: спочатку до першої, потім до другої і т. д., доки не здійсниться перехоплення. Якщо в блоці інструкції try не закоментовувати жодну стрічку, то виникне помилка виходу за межі масиву, яку перехопить перша інструкція catch:
...
try {
      masuv[14] = 28; // створиться виняток типу IndexOutOfBoundsException
      // Наступний код виконуватися не буде
      zminna = 1 / 0;
      System.out.println(В блоці try немає помилок!);
}
// Виконається перехоплення цією інструкцією catch
catch(IndexOutOfBoundsException vunjatok) {
      System.out.println(Помилка виконання програми:  + vunjatok);
}
Якщо в блоці інструкції try закоментувати перший вираз, то:
...
try {
      // masuv[14] = 28;
      zminna = 1 / 0; // створиться виняток типу ArithmeticException
      // Наступний код виконуватися не буде
      System.out.println(В блоці try немає помилок!);
}
...
// Виконається перехоплення цією інструкцією catch
catch(ArithmeticException vunjatok) {
      System.out.println(Помилка виконання програми:  + vunjatok);
}
Якщо в блоці інструкції try закоментувати обидва вирази із помилками, то:
...
try {
      // masuv[14] = 28;
      // zminna = 1 / 0;
      // Виведеться повідомлення у консоль
      System.out.println(В блоці try немає помилок!);
}

Важливою є послідовність написаних після try інструкцій catch. Інструкції catch перехоплюють винятки у тому порядку, в якому вони записані — спочатку перевіряється перша інструкція, якщо вона не перехоплює такий тип винятку, то перевіряється наступна і так далі...

Надкласи перехоплюють усі винятки їхніх підкласів. Наприклад, якщо в інструкції перехоплюється виняток класу Exception:
catch(Exception vunjatok) {
  ...
}
то цією інструкцією також будуть перехоплюватися винятки його підкласу RuntimeException і також винятки класу AriphmeticException, який є підкласом класу RuntimeException. Тому буде помилкою після інструкції catch, яка перехоплює винятки надкласу, писати інструкцію catch, яка буде перехоплювати винятки підкласу, адже всі винятки перехоплюватимуться першою інструкцією:
try {
  ...
}
catch(Exception vunjatok) { /* перехоплюються усі винятки класу Exception, а також всі
винятки його підкласів, таких як RuntimeException */
  ...
}
catch(RuntimeException vunjatok) { /* помилка, ця інструкція ніколи не виконуватиметься,
так як усі винятки були перехоплені надкласом Exception попередньої інструкції */
  ...
}

Також для перехоплення кількох типів винятків можна користуватися оператором АБО(|). 
try {
  ...
}
catch(NullPointerException | ArithmeticException vunjatok) { /* перехоплюються винятки
класу NullPointerException або винятки класу ArithmeticException */
  ...
}

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

class MultiCatch { 
public static void main(String args[]) { 
try { 
     int a = args.length; 
       System.out.println("a = " + a); 
       int b = 42 / a; 
       int c[] = { 1 }; 
       c[42] = 99; 
}
 
catch (ArithmeticException e) { 
          System.out.println("ділення на нуль: " + e); 
}
 
catch(ArrayIndexOutOfBoundsException e) { 
           System.out.println("неправильний індекс масиву: " + e); 
}}

Цей приклад, запущений без параметрів, викликає ділення на нуль. Якщо ж ми поставимо в командному рядку один або кілька параметрів, тим самим встановивши змінну «а» значення більше нуля, наш приклад виконає оператор ділення, але в наступному операторі буде порушено виняток виходу індексу за межі масиву ArraylndexOutOfBounds.


.