Тип ShapeSaver.class
равен Class<ShapeSaver>
.Когда он передается в genericsHell()
, компилятору необходимо проверить, является ли Class<ShapeSaver>
подтипом Class<? extends ShapeProcessor<?>
, что сводится к тому, является ли ShapeSaver
подтипом ShapeProcessor<?>
.Отношение подтипа не выполняется, вызов метода завершается неудачей.
То же самое должно быть верно для решения @ Bohemian.Здесь проверка подтипа происходит при проверке границы T
после вывода T
.Это тоже должно провалиться.Похоже, это ошибка компилятора, которая каким-то образом неверно истолковывает правило, что Raw
присваивается Raw<X>
, как если бы Raw
был подтипом Raw<X>
.см. также Enum.valueOf выдает предупреждение для неизвестного типа класса, расширяющего Enum?
Простое решение вашей проблемы - действительно объявить
void genericsHell(Class<? extends ShapeProcessor> a)
, ShapeSaver
- это подтип ShapeProcessor
, и вызов компилируется.
Это не просто обходной путь.Для этого есть веская причина.Строго говоря, для любого Class<X>
, X
должен быть необработанным типом.Например, Class<List>
- это нормально, Class<List<String>>
- нет.Потому что действительно нет класса, который представляет List<string>
;есть только класс, представляющий List
.
Игнорировать строгое предупреждение о том, что вы не должны использовать необработанный типИногда мы должны использовать необработанные типы, учитывая, как устроена система типов Java.Даже основные API Java (Object.getClass()
) используют необработанные типы.
Вы, вероятно, намеревались сделать что-то подобное
genericsHell(ShapeSaver<Circle>.class);
К сожалению, это не разрешено.Java может иметь, но не вводить литерал типа вместе с обобщениями.Это создало много проблем для большого количества библиотек.java.lang.reflect.Type
беспорядок и непригоден для использования.Каждая библиотека должна представить свое собственное представление системы типов для решения проблемы.
Вы можете позаимствовать одну, например, у Guice, и вы сможете
genericsHell( new TypeLiteral< ShapeSaver<Circle> >(){} )
------------------
(научитьсяпропустите скобки вокруг ShaveSaver<Circle>
при чтении кода)
В теле метода genericsHell()
вы получите полную информацию о типе, а не только класс.