Согласно спецификации языка Java , 3-е издание:
Я хочу понять, почему это решение было принято. Что не так с общими исключениями?
(Насколько я знаю, дженерики - это просто синтаксический сахар во время компиляции, и они в Object
любом случае будут преобразованы в .class
файлы, поэтому объявление обобщения дженериков эффективно, как если бы все в нем было Object
. Пожалуйста, исправьте меня, если я ошибаюсь .)
java
generics
exception
language-design
Хосам Али
источник
источник
myList.get(i)
, очевидно,get
все еще возвращаетObject
. Вставляет ли компилятор приведение кA
, чтобы захватить некоторые ограничения во время выполнения? Если нет, то OP прав, что в итоге он сводится кObject
s во время выполнения. (Файл класса, безусловно, содержит метаданныеA
, но это только метаданные AFAIK.)Ответы:
Как сказал Марк, типы не являются reifiable, что является проблемой в следующем случае:
Оба
SomeException<Integer>
иSomeException<String>
стерты до одного и того же типа, у JVM нет способа различить экземпляры исключений и, следовательно, нет способа определить, какойcatch
блок должен быть выполнен.источник
Вот простой пример того, как использовать исключение:
Тело оператора TRy выдает исключение с заданным значением, которое перехватывается предложением catch.
Напротив, следующее определение нового исключения запрещено, поскольку оно создает параметризованный тип:
Попытка скомпилировать вышесказанное сообщает об ошибке:
Это ограничение имеет смысл, потому что почти любая попытка поймать такое исключение должна потерпеть неудачу, потому что тип не может быть переопределен. Можно ожидать, что типичное использование исключения будет выглядеть примерно так:
Это недопустимо, потому что тип в предложении catch не является пригодным для повторного использования. На момент написания этой статьи компилятор Sun сообщал о каскаде синтаксических ошибок в таком случае:
Поскольку исключения не могут быть параметрическими, синтаксис ограничен, поэтому тип должен быть записан как идентификатор без следующего параметра.
источник
По сути, потому что он был спроектирован плохо.
Эта проблема предотвращает чистый абстрактный дизайн, например,
Тот факт, что предложение catch для дженериков не выполнено, не является оправданием. Компилятор может просто запретить конкретные обобщенные типы, которые расширяют Throwable или запрещать обобщенные типы внутри предложений catch.
источник
EntityNotFoundException
. Но это сделает дженерики бесполезными.Обобщения проверяются во время компиляции на корректность типов. Информация об общем типе затем удаляется в процессе, называемом стиранием типа . Например,
List<Integer>
будет преобразован в неуниверсальный типList
.Из-за стирания типа параметры типа не могут быть определены во время выполнения.
Предположим, вам разрешено расширяться
Throwable
следующим образом:Теперь давайте рассмотрим следующий код:
Из-за стирания типа среда выполнения не будет знать, какой блок catch выполнить.
Поэтому это ошибка времени компиляции, если универсальный класс является прямым или косвенным подклассом Throwable.
Источник: Проблемы с стиранием типов
источник
Я ожидаю, что это потому, что нет способа гарантировать параметризацию. Рассмотрим следующий код:
Как вы заметили, параметризация - это просто синтаксический сахар. Тем не менее, компилятор пытается обеспечить согласованность параметров во всех ссылках на объект в области компиляции. В случае исключения компилятор не может гарантировать, что MyException выбрасывается только из области, которую он обрабатывает.
источник