Error-ів боятися – джавою не писати! Напевно, ти вже дещо знаєш про винятки в Java. Сьогодні хоча б поверхове знання тобі стане в нагоді: ми будемо розбирати клас Error і особливий тип винятків, який багатьох «лякає», з’являючись у їхніх Стектрейсах.

На чолі ієрархії винятків у Java стоїть клас Throwable, у якого є два спадкоємці:

  • Exception, який відповідає за помилки у системі.
  • І наш сьогоднішній герой — Error, який відповідає за помилки JVM.
    Варто сказати, що це скоріше навіть не помилки, а проблеми, які зазвичай не залежать від розробника.

Що робити з Error

Відловлюючи “еррори”, виконати будь-які дії в блоці catch, окрім логування, тобі не вдасться, оскільки це проблеми власне JVM.

Логування — гарна справа: отримавши помилку під час виконання програми, ти можеш подивитися в логи, побачити причину поломки та знати, що виправляти.

Оскільки ти не знаєш, який error можеш отримати, створюючи свій код, вписувати в блок catch якийсь конкретний тип немає сенсу. Використовувати власне клас Error — теж не найвдаліше рішення: у такому разі будеш ловити лише помилки.

Тому краще використовувати клас Throwable, який може зловити і винятки типу Error, і Exception. Як це виглядає на практиці

Так писати не ОК:

try {
    //Твій код
} catch (OutOfMemoryError outOfMemoryError) {
    //Код для отловки OutOfMemoryError
}
Так писати — теж не ОК:

try {
    //Твій код
} catch (Error error) {
    //Код для відловлювання всіх Error
}
А ось так писати — ОК:

try {
    //Твій код
} catch (Throwable throwable) {
    //Код для відловлювання всіх Throwable
}

Другий варіант обробки error-ів — це прокидання їх далі за допомогою ключового слова throws на рівні методу. Такий спосіб використовують у випадках, коли твій код теоретично може кинути помилку типу error, і ти хочеш повідомити це всім, хто буде використовувати твій код, щоб вони могли його обробити.

Поширені error-и

Одні з найпопулярніших ерорів — класи OutOfMemoryError та StackOverflowError.

OutOfMemoryError часто з’являється у тих випадках, коли програмі не вистачає місця для створення об’єктів, збирач сміття обробити не встигає, і як результат – OutOfMemoryError.

В Java ти не можеш контролювати видалення об’єктів, щоб запобігти витоку пам’яті, але ти можеш не смітити, щоб не давати зайвої роботи Garbage Collector-у і не засмічувати heap (купу).

Наприклад, код такого типу породжуватиме багато сміття в пам’яті:


while (true) {
    new Object();
}

Друга помилка, про яку хочу тобі розповісти, — це StackOverflowError: викидається у випадках, коли переповнюється стек. Оскільки стек в основному зберігає локальні змінні, параметри та виклики методів, дуже частою причиною цього є рекурсія, або рекурсивний виклик методу:


public void foo() {
    foo();
}

Сучасні IDE часто повідомляють про рекурсивний виклик методів, щоб уникнути проблем під час виконання програми.

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

Різниця між винятками типу Error та Exception

Error Exception
Не можна виправити у блоці catch Можна обробити у блоці catch
Не з’явиться під час компіляції Можна зловити на етапі компіляції
Проблеми JVM Проблеми логіки коду
Всі Error uncheked checked та uncheked

Без винятків у Java ніяк, але боятися їх не варто. Просто треба розуміти, що означає кожен із типів, і знати, як їх обробляти. На сьогодні це все. Побачимося!