Отражение Java: получите конкретный тип реализованного универсального интерфейса - PullRequest
5 голосов
/ 21 октября 2011

скажем, у меня есть класс, подобный следующему

public class AtomEntryHandler implements ConsumingHandler<AtomEntry>
{
...
}

Можно ли получить объект класса AtomEntry.class из объекта класса AtomEntryHandler.class?

Я не думал, что это возможно из-за стирания, но друг сказал, что это так.

Ответы [ 4 ]

8 голосов
/ 21 октября 2011

Вы можете получить универсальный тип для интерфейсов и прямых подклассов, но только для конкретной реализации. Например, если у вас есть экземпляр List<T>, вы не сможете узнать, для чего он был параметризован, из-за стирания типа. Если определение класса включает параметризованные типы, которые известны во время компиляции (например, class StringList extends List<String>), то вы можете получить эту информацию.

ParameterizedType pt = (ParameterizedType)AtomEntryHandler.class.getGenericInterfaces()[0];
Class atomEntryClass = (Class)pt.getActualTypeArguments()[0];
4 голосов
/ 21 октября 2011

Я не мог придумать способ определения параметра базового типа в случае реализации интерфейса (это не значит, что его нет). Но это так близко к нему.

import java.lang.reflect.*;
public class Foo {
  static class Bar<T> {
  }
  static class SubBar extends Bar<Integer> {
  }

  public static void main(String argv[]) {
    ParameterizedType pt = (ParameterizedType)SubBar.class.getGenericSuperclass();
    Type[] t = pt.getActualTypeArguments();
    for (int i=0;i<t.length;i++) {
       System.out.println(t[i]);
    }
  }
}

Результат: class java.lang.Integer

1 голос
/ 26 октября 2011

Если вам известно, что ConsumingHandler является единственным интерфейсом, реализуемым AtomEntryHandler, и вы знаете, что он принимает только один аргумент типа, вы можете сделать это:

interface ConsumingHandler<T> {}

class AtomEntry {}

class AtomEntryHandler implements ConsumingHandler<AtomEntry>
{
    public static void main( String[] args )
    {
        Type[] interfaces = AtomEntryHandler.class.getGenericInterfaces();
        ParameterizedType firstInterface = (ParameterizedType) interfaces[0];
        Class c = (Class) firstInterface.getActualTypeArguments()[0];
        System.out.println(c.getName()); // prints "AtomEntry"
    }
}

В противном случае вы можетепокопайтесь в getGenericInterfaces() и их actualTypeArguments, пока не найдете что-то, похожее на то, что вы ищете.

Но если вам понадобится сделать это в реальном коде, либо что-то, вероятно, пошло неправильнов вашем дизайне, или вы пишете какую-то безумную гениальную библиотеку объект-макетов, и вам не нужно, чтобы мы отвечали на эти вопросы.

0 голосов
/ 21 октября 2011

В блоге есть подробное описание: Reflecting Generics.

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