3. Обгортання винятків

Checked-винятки здавалися чимось класним у теорії та виявилися повним розчаруванням на практиці.

Припустимо, у вас у проєкті є суперпопулярний метод, який викликається із сотень місць програми. І ви вирішили додати в нього новий checked-виняток. І цілком може виявитися, що цей checked-виняток дійсно такий важливий і особливий, що тільки метод main() знає, що робити у разі захоплення цього винятку.

Тому вам доведеться додати checked-винятки в throws всіх методів, які викликають ваш суперпопулярний метод. А також в throws всіх методів, які викликають ті методи. І в методи, які викликають ті методи.

В результаті у вас в throws у половини методів проєкту буде доданий новий checked-виняток. А потім виявиться, що у вас проєкт покритий тестами, і тести не компілюються. І вам доведеться правити throws ще й у тестах.

А потім весь ваш код (зміни в сотнях файлів) повинні будуть рев’ювити інші програмісти. І тут ми запитуємо себе: а заради чого ми вносили в проєкт дохреналіон змін? День(дні?) роботи, зламані тести, і все заради додавання одного checked-винятку??

Адже є ще проблеми з наслідуванням та перевизначенням методів. Проблем від checked-винятків набагато більше, ніж користі. Загалом зараз мало хто їх любить і мало хто використовує.

Однак все ще багато кодів (зокрема код стандартних бібліотек Java) містять ці самі checked-винятки. І що ж із ними робити? Ігнорувати не можна, обробляти – невідомо як.

Java-програмісти запропонували «загортати» checked-винятки всередину RuntimeException. Інакше кажучи, перехоплювати всі checked-винятки, створювати замість них unchecked-винятки (наприклад, RuntimeException) і викидати вже їх. Виглядає все це приблизно так:

try
{
   код, де може виникнути checked-виняток
}
catch(Exception exp)
{
   throw new RuntimeException(exp);
}

Не дуже красиве рішення, але нічого кримінального: виняток просто поклали всередину винятку RuntimeException.

За бажання його можна звідти легко дістати. Приклад:

Код Примітка
try
{
   // код, де ми запакували checked виняток
   // в RuntimeException
}
catch(RuntimeException e)
{
   Throwable cause = e.getCause();
   if (cause instanceof Exception)
   {
      Exception exp = (Exception) cause;
      // тут код по обработке Exception
   }
}







Отримуємо виняток, збережений всередині об’єкта RuntimeException. cause може бути null

Визначаємо його тип та перетворюємо до змінної checked -типу.