JavaRush /Курси /JAVA 25 SELF /Ієрархія винятків у Java

Ієрархія винятків у Java

JAVA 25 SELF
Рівень 24 , Лекція 0
Відкрита

1. Клас Throwable: корінь усіх винятків

Зараз докладно розглянемо, як побудована система винятків у Java: що таке Throwable, чим відрізняються Exception і Error, а також що означають «перевірюваний» і «неперевірюваний» винятки. Це фундамент для грамотної обробки помилок у ваших програмах.

У Java усі винятки й помилки — це обʼєкти, які наслідуються від класу java.lang.Throwable.
Throwable — кореневий клас ієрархії винятків у Java.

Схематично:

Throwable
├── Exception
└── Error

Throwable — базовий клас для всього, що може бути «викинуте» (throw) і «спіймане» (catch) у Java. Його не можна використовувати безпосередньо — він слугує основою для конкретніших типів помилок.

Exception — для «нормальних» помилок

Exception — базовий клас для всіх винятків, що можуть виникнути у програмі й які можна й потрібно обробляти. Це «робочі» помилки: проблеми з файлами, мережею, введенням-виведенням, помилками користувача тощо. Більшість ваших try-catch працюватиме саме з нащадками Exception.

Приклади:

  • IOException — помилка під час роботи з файлами або мережею.
  • SQLException — помилка під час роботи з базою даних.
  • FileNotFoundException — файл не знайдено.

Error — для фатальних помилок JVM

Error — базовий клас для помилок, які відбуваються на рівні віртуальної машини Java (JVM). Зазвичай це критичні збої, які програма не може і не повинна обробляти. Якщо виник Error — швидше за все, застосунок не зможе продовжити роботу.

Приклади:

  • OutOfMemoryError — закінчилася памʼять.
  • StackOverflowError — переповнення стеку (наприклад, через нескінченну рекурсію).
  • NoClassDefFoundError — не знайдено потрібний клас.

Важливо:
Ловити й обробляти Error — майже завжди погана ідея. Це не помилки вашої програми, а збої середовища виконання.

2. Checked vs Unchecked: що це означає?

У Java усі винятки поділяються на дві великі групи:

Перевірювані (Checked) винятки

Що це? Винятки, які компілятор змушує обробити або явно передати далі.

Коли виникають? Зазвичай повʼязані із зовнішніми ресурсами: файлами, мережею, базами даних, введенням користувача.

Як обробляти? Потрібно або обернути код у try-catch, або додати throws у сигнатуру методу.

Приклади: IOException, SQLException, FileNotFoundException

Приклад:

public void readFile(String path) throws IOException {
    FileReader reader = new FileReader(path); // може викинути IOException
    // ...
}

Якщо не обробити або не передати далі — програма не скомпілюється!

Неперевірювані (Unchecked) винятки

Що це? Винятки, які не потребують обовʼязкової обробки компілятором.

Коли виникають? Зазвичай це помилки в логіці програми: ділення на нуль, вихід за межі масиву, звернення до null.

Як обробляти? Можна ловити, але не обовʼязково. Краще запобігати таким помилкам за допомогою перевірок.

Де в ієрархії? Усі наслідуються від RuntimeException.

Приклади: NullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentException, ArithmeticException

Приклад:

int[] arr = {1, 2, 3};
System.out.println(arr[10]); // ArrayIndexOutOfBoundsException

Компілятор не вимагає обробки, але програма «впаде» у разі помилки.

3. Уся ієрархія на одній картинці

graph TD
    Throwable --> Error
    Throwable --> Exception
    
    Exception --> RuntimeException
    Exception --> CheckedExceptions["(інші Checked Exceptions)"]
    
    Error --> OutOfMemoryError
    Error --> StackOverflowError
    
    RuntimeException --> NullPointerException
    RuntimeException --> IndexOutOfBoundsException
    RuntimeException --> IllegalArgumentException

    %% Стилі
    style Throwable fill:#ffa64d,color:#000
    style Exception fill:#ffa64d,color:#000
    style CheckedExceptions fill:#ffa64d,color:#000
    
    style Error fill:#ff4d4d,color:#fff
    style OutOfMemoryError fill:#ff4d4d,color:#fff
    style StackOverflowError fill:#ff4d4d,color:#fff
    
    style RuntimeException fill:#4dff88,color:#000
    style NullPointerException fill:#4dff88,color:#000
    style IndexOutOfBoundsException fill:#4dff88,color:#000
    style IllegalArgumentException fill:#4dff88,color:#000

Таблиця: основні відмінності

Група Батьківський клас Потребує обробки? Приклади
Checked Exception
Exception
Так
IOException, SQLException
Unchecked
RuntimeException
Ні
NullPointerException, IndexOutOfBoundsException
Error
Error
Ні
OutOfMemoryError, StackOverflowError

4. Як це виглядає в коді?

Checked Exception: приклад із файлами

import java.io.*;

public class FileDemo {
    public static void main(String[] args) {
        try {
            FileReader reader = new FileReader("nofile.txt"); // FileNotFoundException (checked)
            int data = reader.read();
            System.out.println(data);
            reader.close();
        } catch (IOException e) {
            System.out.println("Помилка під час роботи з файлом: " + e.getMessage());
        }
    }
}

Компілятор змусить обробити IOException!

Unchecked Exception: приклад із діленням на нуль

public class ExceptionDemo {
    public static void main(String[] args) {
        int a = 10;
        int b = 0;
        int c = a / b; // ArithmeticException (unchecked)
        System.out.println("Результат: " + c);
    }
}

Компілятор не вимагає обробки, але програма «впаде».

5. Навіщо потрібна ієрархія винятків?

  • Гнучкість обробки: можна ловити як конкретні помилки (FileNotFoundException), так і цілі групи (IOException або Exception).
  • Повторне використання коду: можна централізовано обробляти помилки одного типу.
  • Чистота коду: основна логіка не засмічується перевірками на кожну дрібницю.

Приклад:

try {
    // небезпечний код
} catch (FileNotFoundException e) {
    System.out.println("Файл не знайдено!");
} catch (IOException e) {
    System.out.println("Помилка введення-виведення!");
} catch (Exception e) {
    System.out.println("Щось пішло не так: " + e.getMessage());
}

6. Типові помилки під час роботи з винятками

Помилка № 1: Ігнорування винятків. Писати catch (Exception e) {} — погано! Ви втрачаєте інформацію про причину помилки.

Помилка № 2: Ловимо занадто багато. catch (Exception e) ловить усе підряд, навіть те, чого не очікували. Краще ловити лише ті винятки, які вмієте обробляти.

Помилка № 3: Ловимо помилки (Error). Не варто ловити Error, якщо ви не пишете низькорівневий код. Це проблеми JVM, а не вашої програми.

Помилка № 4: Не розрізняємо checked і unchecked. Не всі винятки однакові! Checked потребують обробки (Exception), unchecked — ні (RuntimeException та нащадки).

Помилка № 5: Не додаємо інформації до винятків. Якщо створюєте свої винятки — завжди додавайте інформативне повідомлення.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ