В хорошо разработанной структуре исключений следует проводить различие между исключениями, которые в некоторой степени "ожидаемы", и теми, которые не являются. Java пытается использовать проверенные и непроверенные исключения для этого. По этому стандарту IOException должно быть проверенным исключением.
Фундаментальная проблема, однако, заключается в том, что часто код будет написан с (возможно, разумным) ожиданием того, что определенное исключение не произойдет, и с его помощью ничего не поделать, если оно произойдет. Если метод объявлен как выбрасывающий определенное проверенное исключение, Java позволяет вызывающей стороне игнорировать исключение, если он объявляет себя как выбрасывающее это исключение, но нет способа, с помощью которого метод или блок кода могут указывать эти определенные исключения из вызываемых методов не ожидается . Распространенным анти-паттерном является:
try
{
methodThatsDeclaredAsThrowingFooExceptionButWont()
}
catch FooException Ex
{
// Never going to happen
}
Очевидное предположение состоит в том, что, поскольку метод не будет вызывать FooException, и единственная причина, по которой catch
, заключается в том, чтобы сделать компилятор счастливым, у catch
нет никаких причин что-либо делать. Коварен, потому что если FooException
будет брошено по какой-либо причине, оно останется незамеченным.
Альтернативой является метод, который вызывает methodThatsDeclaredAsThrowingFooExceptionButWont для объявления себя как throws FooException
или throws Exception
, но это также не совсем подходит. Если метод, который не должен генерировать FooException
, делает, состояние системы может отличаться от того, которое ожидалось бы, когда генерируется FooException
.
Например, предположим, что кто-то пытается загрузить документ, но процедура загрузки документа должна прочитать некоторые не относящиеся к документу таблицы перевода, которые должны храниться в фиксированном месте; Если эта попытка не удалась, наличие IOException
перколата до вызывающей стороны будет означать, что при загрузке документа возникла проблема. Если подпрограмма load-document не подготовлена для разумной обработки вероятности сбоя подпрограммы load-translation-tables, такой сбой не должен просачиваться так же, как и IOException
, произошедший при фактической загрузке документа.
Надлежащим средством правовой защиты было бы не исключение IOException
как непроверенное исключение, а скорее наличие декларативного средства, с помощью которого код мог бы указывать, что одному или нескольким видам проверенных исключений не разрешается просачиваться из определенный блок из вызванных таким образом методов, но вместо этого его следует заключить в какой-то другой тип исключения (например, RuntimeException).