Преобразовать java.lang.reflect.Type в класс <T> clazz

Как преобразовать java.lang.reflect.Type в Class<T> clazz?

Если у меня есть один метод, следующий, у которого есть аргумент Class<T>:

public void oneMethod(Class<T> clazz) {     
    //Impl
}

Затем другой метод, имеющий аргумент java.lang.reflect.Type и вызывающий oneMethod(Class<T> clazz), и для этого мне нужно преобразовать java.lang.reflect.Type type в Class<T>:

public void someMehtod(java.lang.reflect.Type type) {
   // I want to pass type arg to other method converted in Class<T>
   otherMethod(¿How to convert java.lang.reflect.Type to Class<T>?);
}

Возможно ли это?

Ответ 1

Вы должны убедиться, что type является экземпляром Class, а затем произведите его.

if (type instanceof Class) {
  @SuppressWarnings("unchecked")
  Class<?> clazz = (Class<?>) type;
  otherMethod(clazz);
}

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

Ответ 2

Если вы хотите использовать библиотеку, вы можете использовать com.google.guava:guava:12+:

Class<?> clazz = com.google.common.reflect.TypeToken.of(type).getRawType();

В качестве альтернативы вы также можете использовать com.fasterxml.jackson.core:jackson-databind:2.8.x:

Class<?> clazz = com.fasterxml.jackson.databind.type.TypeFactory.rawClass(type);

Это обрабатывает все случаи правильно, и вы получите стертый класс вашего типа.

Ответ 3

Энди Тернер ответит правильно, однако, если вам нужно извлечь класс из параметра типа, это полный пример:

private static class MyClass extends ArrayList<Integer> {
}

public static void main(String[] args) {

    ParameterizedType arrayListWithParamType
            = (ParameterizedType) MyClass.class.getGenericSuperclass();

    Type integerType = arrayListWithParamType.getActualTypeArguments()[0];

    Class<?> integerClass = (Class<?>) integerType;

    System.out.println(integerClass == Integer.class);
}

Ответ 4

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

1) чтобы быть уверенным в общем во время выполнения, мы делаем так:

class MyClass<E> {}

а потом:

MyClass<TargetType> genericAwaredMyClassInctance = new MyClass<TargetType>(){};

пожалуйста, обратите внимание на {} в конце. Это означает анонимные расширения MyClass. Это важный нюанс.

2) позвольте улучшить MyClass, чтобы иметь возможность извлекать тип во время выполнения.

class MyClass<E> {

    @SuppressWarnings("unchecked")
    protected Class<E> getGenericClass() throws ClassNotFoundException {
        Type mySuperclass = getClass().getGenericSuperclass();
        Type tType = ((ParameterizedType)mySuperclass).getActualTypeArguments()[0];
        String className = tType.getTypeName();

        return (Class<E>) Class.forName(className);
    }

}

и, наконец, используйте это так:

MyClass<TargetType> genericAwaredMyClassInctance = new MyClass<TargetType>(){};

assert(genericAwaredMyClassInctance.getGenericClass() == TargetType.class)

Ответ 5

Было бы странно, что Type будет чем-то другим, чем Class... Javadoc для Type говорит

Все известные классы реализации:     Класс

Поэтому, если у вас нет специальных библиотек, которые используют не Class Type s, вы можете просто выполнить их, но вы должны быть готовы к возможному ClassCastException. Опасайтесь: Java использует недокументированную реализацию типа для представления дженериков, см. Ниже.

Вы можете явно обработать его или нет, потому что это исключение:

Явный способ:

try {
    Class<?> clazz = (Class<?>) type;
}
catch (ClassCastException ex) {
    // process exception
}

Неявный способ:

Class<?> clazz = (Class<?>) type;

но текущий метод может...


EDIT за комментарий @Andy Turner:

Остерегайтесь: Type type = new ArrayList<String>().getClass().getGenericSuperclass(); дает что-то типа, но не класс. Это ParameterizedType, поэтому вы можете использовать метод getRawType() для поиска фактического класса, но могут существовать другие.

Ответ 6

Вы имели в виду это?

public <T extends Type> void oneMethod(T clazz) {

}

public void someMethod(Type type) {
    oneMethod(type);
}