#java #generics #reflection
#java #дженерики #отражение
Вопрос:
Я парень с C #, изучающий Java, и я пытаюсь понять, как дженерики работают в Java.
Учитывая класс или интерфейс «что-то», я знаю, что могу сделать это, чтобы получить класс этого типа:
Something.class
Теперь, учитывая общий интерфейс
Я бы хотел написать
(GenericInterface<SomeClass>).class
но компилятору это не очень нравится.
Спасибо за любую помощь.
Комментарии:
1. Вы пытаетесь определить, что такое класс SomeClass?
Ответ №1:
Это потому, что благодаря стиранию нет GenericInterface<SomeClass>
класса. Есть просто GenericInterface
класс, у которого есть общий параметр.
Если вы хотите, чтобы вы могли вызывать общие типобезопасные методы, такие как Class.cast()
или Class.newInstance()
, тогда вам не повезло. Дженерики — это, по сути, концепция времени компиляции; во время выполнения недостаточно информации для выполнения общих проверок, и поэтому эти методы не могут быть типобезопасными для произвольного Class
экземпляра.
Лучшее, что вы можете сделать в этом случае, это использовать «raw» GenericInterface.class
, а затем GenericInterface<SomeClass>
сразу же после этого явно привести результаты. Это правильно выдаст «непроверенное» предупреждение, поскольку, как упоминалось выше, нет проверки во время выполнения, что объект действительно имеет правильный общий параметр, и JVM просто должна поверить вам на слово.
(В том же духе, если вы пытаетесь выполнить какую-то instanceof
проверку, то это тоже просто невозможно. Объект не имеет универсального параметра для своего класса; только переменные, которые вы ему назначаете. Итак, опять же, эти проверки во время выполнения просто невозможны из-за ограничений дизайна языка.)
Ответ №2:
Дженерики принципиально отличаются в Java и C #, потому что в Java дженерики проверяются во время компиляции, но затем изменяются на конкретный класс в процессе, известном как стирание типа. Используя ваш пример, GenericInterface<SomeClass>
становится GenericInterface
во время выполнения.
Это немного недооцененная реализация дженериков, и, как вы видите, она создает некоторые проблемы (которые вы обычно можете обойти). Это было сделано таким образом, чтобы поддерживать обратную совместимость со старыми версиями Java.
Комментарии:
1. Это не наполовину, это менее ограничительно. В некотором смысле это открывает больше возможностей для динамических языков, которые работают на JVM. Конструкции, которые CLR просто не может выполнить. Итак, я хочу сказать: это просто вопрос перспективы.
Ответ №3:
Нет, дженерики Java так не работают.
Вы можете сделать GenericInterface.class
, чтобы получить доступ к неродовому корневому классу, но для общей версии нет отдельного класса.