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-типа.