Тип выражения
b ? new Excep1() : new Excep2()
равен Exception
, поскольку это общий супертип Excep1
и Excep2
.
Однако вы не перехватываете Exception
, поэтому компилятор жалуется на это.
Если вы поймаете Exception
, он пройдет компиляцию:
public int m2(boolean b) {
try {
throw b ? new Excep1() : new Excep2();
} catch (Exception e) {
return 0;
}
}
Я попытался найти запись JLS, которая объясняет тип условной троицы выражение в вашем примере.
Все, что я смог найти, это то, что это конкретное выражение является 15.25.3. Ссылочное условное выражение .
Я не совсем уверен, считается ли оно поли-выражением или автономным выражением. Я думаю, что это автономно (поскольку поли-выражения включают контекст присваивания или контекст вызова, и я не думаю, что оператор throw
считается одним из них).
Для автономного выражения: «Если второе и третий операнд имеет один и тот же тип (который может быть нулевым), тогда это тип условного выражения. "
В вашем случае второй и третий операнды имеют три общих типа - Object
, Throwable
и Exception
- тип выражения должен быть одним из двух последних, поскольку «выражение в выражении throw должно обозначать переменную или значение ссылочного типа, который можно назначить (§5.2) для тип Throwable. "
Похоже, что компилятор выбирает наиболее конкретный c общий тип (Exception
), и поэтому catch (Exception e)
решает ошибку компиляции.
Я также попытался заменить ваши два пользовательских исключения двумя подклассами IOException
, и в этом случае catch (IOException e)
устраняет ошибку компиляции.