Почему Java multi-catch не может работать с типами, связанными с использованием подклассов?
Вот фрагмент кода, который не должен компилироваться:
void multiCatch()
{
try {
throwIOFile();
}
// FileNotFoundException extends IOException, hence this
// does not compile ("alternatives" related by sub classing):
catch (IOException | FileNotFoundException e) { }
}
void throwIOFile() throws IOException, FileNotFoundException
{}
Все работает как очарование, если бы не типы исключений были связаны подклассами. Если вы поменяете IOException
в моем фрагменте кода, скажем.. SQLException
, оно работает. Спецификация гласит:
Это ошибка времени компиляции, если объединение типов содержит две альтернативы Di и Dj (i ≠ j), где Di является подтипом Dj.
Я не могу понять обоснование этого. Конечно, multi-catch в моем примере полностью избыточен, так как я мог бы также поймать IOException
только. Но что может быть вредным в том, чтобы сделать мой фрагмент кода легальным? Конечно, должен быть вред, чтобы практика стала незаконной?
3 ответа
В спецификации обсуждается, что
Предложение multi-catch можно рассматривать как последовательность предложений uni-catch
так что ваш код вроде
try {
throwIOFile();
}
catch (IOException e) { }
catch (FileNotFoundException e) { } // error
Это также отвергается Javac. В этом случае ошибка оправдана, так как 2-е предложение недоступно.
Однако я не думаю, что тип объединения должен быть запрещен. Это должно быть предупреждение в лучшем случае.
Наличие подклассов данного исключения в одном и том же улове просто не имеет никакого смысла, и это сбивает с толку, потому что вы все равно будете вводить улов независимо от того, какие подклассы вы укажете. Например, почему вы собираетесь писать
catch (IOException | FileNotFoundException e)
если
catch (IOException e)
будет иметь точно такое же поведение? Это просто сбивает с толку.
Но что может быть вредным в том, чтобы сделать мой фрагмент кода легальным? Конечно, должен быть вред, чтобы практика стала незаконной?
Это сбивает с толку код - вы можете упростить код, просто ловя IOException
в то время как, похоже, вам действительно нужно поймать их обоих по отдельности.
Я не могу с уверенностью сказать, что это обоснование, но это обоснование я бы использовал, чтобы оправдать его. Остановите разработчиков от злоупотребления функцией, когда они могут просто написать более простой код для начала.