How can I convert java.lang.reflect.Type
to Class
?
If I have one method as next which has an argument of Class
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.
Did you mean this?
public <T extends Type> void oneMethod(T clazz) {
}
public void someMethod(Type type) {
oneMethod(type);
}
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 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);
}
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
Type
s, 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.
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)