Свойство универсального списка, получить тип универсального - PullRequest
1 голос
/ 07 октября 2011

У меня есть класс, у которого есть свойство List<String> или List<SomeObject>.

. Я получаю тип свойства следующим образом:

propertyClass = PropertyUtils.getPropertyType(currentObject, property);

Что я хочу сделать, это проверить, что propertyClass является List<SomeType> и получить объект класса для типа в списке.После этого я захочу создать ArrayList данного типа и заполнить его объектом этого типа (все создано динамически, я буду использовать это для динамической загрузки некоторых данных из файла).

Есть лиКак я могу сделать это с помощью отражения?

Ответы [ 3 ]

7 голосов
/ 07 октября 2011

Обобщения стираются после компиляции (из-за стирания типа ). Поэтому вы не можете использовать их во время выполнения.

0 голосов
/ 25 апреля 2014

Я нашел другой ответ Боба Ли, Свена Моусона и Джесси Уилсона:

[открытый класс TypeToken:] Представляет универсальный тип T. Java пока не предоставляет способ представленияуниверсальные типы, так что этот класс делает.Вынуждает клиентов создавать подкласс этого класса, который позволяет получать информацию о типе даже во время выполнения.

Источник: http://google -gson.googlecode.com / svn / trunk / gson / docs/javadocs/com/google/gson/reflect/TypeToken.html

Существует даже пример использования List<String>, и он действительно работает.TypeToken будет иметь rawType из java.util.List, а typeArguments установлено в [java.lang.String].Здесь нет стирания типа!Однако это также не работает для подстановочных знаков, таких как List<? extends Foo>.

Обратите внимание, что это немного отличается от другого решения, которое я объяснил в моем другом ответе.Здесь вы не анализируете свойство Java-бина, чтобы получить информацию о типе.Здесь вы фактически создаете поле, в котором хранится информация о типе.Я не могу найти ни одного общедоступного конструктора или фабричного метода для создания TypeToken из информации о типах, которую вы получили другим способом.Поэтому я думаю, что он действительно может использоваться только как пустой анонимный внутренний класс.

0 голосов
/ 17 апреля 2014

У меня похожая проблема, и я действительно нашел решение, которое работает для меня!

Это можно сделать, но это может быть ненадежно (то есть не работает во всех ситуациях).Сначала нужно получить «Поле» (через отражения).Затем получите «GenericType».Затем попробуйте привести это к «ParameterizedType».Это возможно, если у него действительно есть параметр.Затем получите «ActualTypeArguments».Обычно это классы, поэтому вы можете привести их (если не можете попробовать Class.forName (...)), и тогда у вас уже есть тип элементов в списке.

Однако,это не сработает, если я сделаю это:

class MyList extends List<String> {... }

А потом:

MyList list = new MyList(); // This would be List<String>

На самом деле вам нужно проверить тип, чтобы увидеть, является ли он списком и имеет ли онтип, объявленный в любом классе или интерфейсе.Но их может быть больше одного, и тип может быть привязан ко многим интерфейсам, а не только к одному классу.конечно, вы могли бы просто игнорировать свойства, которые не являются «List», и, возможно, выдать ошибку компилятора, если она есть (я, вероятно, просто сделаю это).

Тогда есть проблема с подстановочными знаками: List list= ... Все, что вы можете сделать, это заменить его на «Объект», но это небезопасно, если вы хотите добавить элементы в список!(опять же, вы можете проверить это во время компиляции и выдать ошибку, если есть подстановочные знаки)

Другое решение - использовать проверенный список (см. Collections.checkedList (List, Class)) и попытаться получить этот типво время выполнения (вам, вероятно, нужно размышление для этого).Это будет работать намного лучше и будет гораздо надежнее, чем просто дженерики.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...