A RuntimeException
может быть сгенерировано любым кодом. Другими словами, компилятор не может легко предсказать, какой код может его генерировать. RuntimeException
может быть перехвачен блоком catch(Exception e)
.
IOException
, однако, является проверенным исключением - это могут делать только вызовы методов, которые объявлены как выброшенные Компилятор может быть (разумно) уверен, что это не может произойти, если нет вызовов метода, которые объявлены для его выброса.
Компилятор Java просто не учитывает ситуацию «кода вообще нет в блоке try» - он всегда позволяет перехватывать непроверенные исключения, поскольку во всех разумных сценариях будет код, который может потенциально генерировать непроверенное исключение.
Из секции 14.21 JLS:
Блок захвата C доступен, если выполняются оба следующих условия:
- Некоторые выражения или оператор throw в блоке try достижимы и могут генерировать исключение, тип которого можно назначить параметру предложения catch C. (Выражение считается достижимым, если самый внутренний оператор, содержащий его, достижим.)
- В операторе try нет более раннего блока catch A, так что тип параметра C такой же, как или подкласс типа параметра A.
Возможно, компилятор должен понимать, что в вашем блоке try в вашем первом случае есть нет выражений ... похоже, это все еще недоступное предложение catch, для меня.
РЕДАКТИРОВАТЬ: Как отмечено в комментариях, раздел 14.20 содержит это:
Ошибка времени компиляции, если предложение catch
перехватывает проверенный тип исключения E1 , но не существует проверенного типа исключения E2 , так что выполняются все следующие условия:
- E2 <: <em>E1
- Блок
try
, соответствующий предложению catch
, может выдать E2
- Нет предшествующего
catch
блока непосредственно включенного оператора try, перехватывает E2 или супертип E2 .
если E1 не является исключением класса.
Похоже, это то, что вы на самом деле испортили, но спецификация не так ясна, как могла бы быть с точки зрения недоступных блоков улова в 14.21.