Отражение обобщенных Java: тип подкласса общего поля - PullRequest
4 голосов
/ 10 августа 2010

Учитывая два класса, как это:

class Example1<A,B> {

  public Map<A,B> someMap = new HashMap<A,B>();

}

class Example2 extends Example1<URL, URL> {


}

Есть ли способ с помощью отражения, что я могу определить типы компонентов карты для Example2?

Я знаю, что могу сделать:

ParameterizedType t = (ParameterizedType) Example2.class.getFields()[0].getGenericType();

Но оттуда я не могу понять, что эти два компонента являются URL-адресами.

У кого-нибудь естьидеи?

Ответы [ 4 ]

7 голосов
/ 10 августа 2010

Даррон не совсем прав. Следующее напечатает то, что вы хотите:

ParameterizedType superClass = (ParameterizedType) Example2.class.getGenericSuperclass();
System.out.println(superClass.getActualTypeArguments()[0]);
System.out.println(superClass.getActualTypeArguments()[1]);

Распечатывает:

class java.net.URL
class java.net.URL
1 голос
/ 05 января 2011

В API отражения Java нет метода, который напрямую дает то, что вы хотите, но он предоставляет всю основную информацию, необходимую для возможности вычисления с помощью Field.getGenericType() и Class.getGenericSuperclass().Но решить эту проблему в целом для любой иерархии классов и типа поля нетривиально.

Для этого вычисления вы можете использовать библиотеку gentyref .В вашем примере вы можете получить тип переменной someMap следующим образом:

Type someMapType = GenericTypeReflector.getExactFieldType(
   Example2.class.getField("someMap"),
   Example2.class);

Если доступно достаточное количество информации (а в примере 2 это так), то someMapType будет ParameterizedType ,Затем вы можете получить тип ключа и значение, например:

((ParameterizedType)someMapType).getActualTypeArguments();

Это будет массив, содержащий URL.class дважды.Обратите внимание, что он может содержать и другие вещи, кроме классов (например, другой ParameterizedType).Поэтому, если вы хотите сделать что-то нетривиальное с этим типом (например, посмотрите, является ли это супертипом другого типа), другие методы в GenericTypeReflector также могут пригодиться ...

[Яавтор gentyref]

1 голос
/ 11 августа 2010

Ваш ответ не совсем правильный - вы возвращаете универсальные типы класса, а не типа поля "someMap".

Конечно, в приведенном примере аргументы для someMap были такими же, как аргументы для класса, но если были определены someMap с, и типы карт не были оба URL, то возникает вопрос для сопоставления параметров универсального типа с полями.

Лучшим примером могло бы быть:

class Example1<A,B> {

  public Map<B,A> someMap = new HashMap<B,A>();

}

class Example2 extends Example1<URL, String> {


}

В этом случае, чтобы ответить на вопрос: каковы типы someMap в Example2? Ответ должен быть:

java.lang.String java.net.URL

Но я до сих пор не могу понять, как это получить.

1 голос
/ 10 августа 2010

Поскольку обобщения Java реализованы с помощью «стирания», эта информация недоступна во время выполнения через рефлексию.

РЕДАКТИРОВАТЬ: кажется, я упустил некоторые детали вопроса.В этом специализированном случае доступна информация о типе.

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