37

How can I convert java.lang.reflect.Type to Class<T> clazz?

If I have one method as next which has an argument of Class<T>:

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

Then another method which has an argument of java.lang.reflect.Type and it calls oneMethod(Class<T> clazz) and for it I need to convert java.lang.reflect.Type type to 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>?);
}

Is it possible?

Lii
  • 11,553
  • 8
  • 64
  • 88
Pau
  • 14,917
  • 14
  • 67
  • 94

6 Answers6

37

You have to ensure that type is an instance of Class, and then cast it.

if (type instanceof Class) {
  Class<?> clazz = (Class<?>) type;
  otherMethod(clazz);
}

Of course, you also have to handle the case of it not being a Class.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
23

If you are willing to use a library, you could use com.google.guava:guava:12+:

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

Alternatively you could also use com.fasterxml.jackson.core:jackson-databind:2.8.x:

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

This handles all cases correctly and you will get the type-erased class of your type.

Daniel Beer
  • 1,709
  • 1
  • 14
  • 15
3

Using generic types in runtime is a little bit tricky in Java. And I think this is a root cause of your issue.

1) to be sure about generic in runtime we doing like this:

class MyClass<E> {}

and then:

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

please pay attention to {} in the end. It means anonymous extends of MyClass. This is an important nuance.

2) let`s improve MyClass to be able to extract the type in runtime.

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);
    }

}

and finally, use it like this:

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

assert(genericAwaredMyClassInctance.getGenericClass() == TargetType.class)
virtuemaster
  • 105
  • 1
  • 8
0

Andy Turner answer is correct, however if you need to retrieve a class from a type parameter this is a complete example:

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);
}
xonya
  • 2,146
  • 29
  • 37
-2

It would be weird that a Type would be anything else than a Class... Javadoc for Type says

All Known Implementing Classes: Class

So unless you have special libraries that use non Class Types, you can simply cast - but you must be ready for a possible ClassCastException. Beware: Java use undocumented Type implementation to represent generics, see below.

You can explicitely process it or not because it is an unchecked exception:

Explicit way:

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

Implicit way:

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

but the current method could throw...


EDIT per @Andy Turner's comment:

Beware: Type type = new ArrayList<String>().getClass().getGenericSuperclass(); yields something that's a Type but not a Class. This one is a ParameterizedType, so you can use getRawType() method to find the actual class, but others might exist.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • 3
    e.g. `Type type = new ArrayList().getClass().getGenericSuperclass();` yields something that's a `Type` but not a `Class`. [Ideone demo](http://ideone.com/kwdkvj). – Andy Turner Aug 04 '16 at 09:30
  • 1
    @AndyTurner: you are right, it is an internal undocumented class... One must guess that it implements `ParameterizedType` and then use `getRawType()` to find a true Class. – Serge Ballesta Aug 04 '16 at 10:26
  • 1
    @SergeBallesta: That's the point. `Type` can be an instance of `Class`, or it can be an instance of `ParameterizedType`, `TypeVariable`, `WildcardType`, or `GenericArrayType`. The latter 4 are interfaces; the implementing class is not relevant. – newacct Aug 05 '16 at 00:50
  • 1
    Don't forget: `All Known Subinterfaces: GenericArrayType, ParameterizedType, TypeVariable, WildcardType` Also don't forget that you can anonymously implement an interface anywhere -- so there may in fact be many classes that implement these interfaces. In practice, other implementations of Type are obtained by calling e.g. `field.getGenericType()`. – Luke Hutchison Jun 19 '18 at 22:44
-5

Did you mean this?

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

}

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