Why can't overriding methods throw exceptions broader than the overridden method?
Почему переопределяющие методы не могут генерировать исключения шире, чем переопределяемый метод?
Я просматривал книгу Кэти Сьерра по SCJP 6 и наткнулся на это объяснение генерирования исключений в переопределенном методе. Я совершенно не понял. Кто-нибудь может мне это объяснить?
Переопределяющий метод НЕ должен генерировать проверенные исключения, которые являются новыми или более широкими, чем те, которые объявлены переопределяемым методом. Например, метод, который объявляет FileNotFoundException, не может быть переопределен методом, который объявляет SQLException, Exception или любое другое исключение вне среды выполнения, если оно не является подклассом FileNotFoundException .
Переведено автоматически
Ответ 1
Это означает, что если метод объявляет, что он генерирует данное исключение, переопределяющий метод в подклассе может объявлять, что он генерирует только это исключение или его подкласс. Например:
@Override publicvoidfoo()throws SQLException {..} // NOT allowed }
SocketException extends IOException, но SQLException этого не делает.
Это из-за полиморфизма:
Aa=newB(); try { a.foo(); } catch (IOException ex) { // forced to catch this by the compiler }
Если бы B вы решили выбросить SQLException , то компилятор не смог бы заставить вас перехватить это, потому что вы ссылаетесь на экземпляр B по его суперклассу - A. С другой стороны, любой подкласс IOException будет обрабатываться предложениями (catch или throws), которые обрабатывают IOException
Правило, по которому вы должны иметь возможность ссылаться на объекты по их суперклассу, - это принцип подстановки Лискова.
Поскольку непроверенные исключения могут генерироваться где угодно, то они не подпадают под действие этого правила. Вы можете добавить непроверенное исключение в предложение throws в качестве формы документации, если хотите, но компилятор ничего не применяет по этому поводу.
Ответ 2
Переопределяемый метод МОЖЕТ генерировать любое непроверенное исключение (во время выполнения), независимо от того, объявляет ли переопределяемый метод исключение
На мой взгляд, это ошибка в конструкции синтаксиса Java. Полиморфизм не должен ограничивать использование обработки исключений. Фактически, другие компьютерные языки этого не делают (C #).
Более того, метод переопределяется в более специализированном подклассе, так что он более сложный и, по этой причине, с большей вероятностью генерирует новые исключения.
Ответ 4
Я привожу этот ответ здесь на старый вопрос, поскольку ни в одном ответе не говорится о том, что переопределяющий метод ничего не может выдать вот снова, что может выдать переопределяющий метод:
4) Наличие RuntimeExceptions в throws не требуется.
В throws могут быть исключения RuntimeExceptions или нет, компилятор не будет жаловаться на это. Исключения RuntimeExceptions не являются проверяемыми исключениями. В бросках должны появляться только проверенные исключения, если они не перехвачены.