ClassCastException when trying to get the generic class type
I tried using the code provided in this answer . I did this:
public class ListClass<T> {
private class ObjectFactory<T> {
//This should the the class of generic type T which is what I need
public final Class<T> cls;
@SuppressWarnings ("unchecked")
public ObjectFactory()
{
//This three lines are from the linked answer - I don't really understand them
Type type = getClass().getGenericSuperclass();
ParameterizedType paramType = (ParameterizedType) type; //java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
cls = (Class<T>) paramType.getActualTypeArguments()[0];
}
public T createNew(... some parameters ...) {
return (T)new Expression(cls, "new", new Object[]{... some parameters ...}).getValue();
}
}
public final ObjectFactory<T> factory = new ObjectFactory<T>();
public generateItem() {
//let add() be method that adds item of type T to this list
this.add(factory.createNew(... some parameters ...));
}
}
How am I wrong?
source to share
This method only works if the class is parameterized with a specific argument like this:
class Sub extends Super<String> {}
And then by extension:
new Super<String>() {}
But not like this:
class Sub<T> extends Super<T> {}
And not like this:
<T> Super<T> m() {
return new Super<T>() {};
}
Usability getActualTypeArguments
is a property of a class, not an instance, so this class needs actual type arguments.
In your edit, what I recommend doing is creating a helper routine for this:
static <T> Class<T> getActualTypeArgument(Class<?> clazz, int i) {
Type superclazz = getClass().getGenericSuperclass();
ParameterizedType paramType = (ParameterizedType) superclazz;
@SuppressWarnings("unchecked")
final Class<T> actual =
(Class<T>) paramType.getActualTypeArguments()[i];
return actual;
}
Then use this on ListClass
:
class ListClass<T> {
private ObjectFactory<T> factory = new ObjectFactory<T>(
getActualTypeArgument(this.getClass(), 0));
}
And create ListClass
for example. in the following way:
ListClass<GameObject> list =
new ListClass<GameObject>() {};
Consider also simply passing Class<T>
to:
class ListClass<T> {
private ObjectFactory<T> factory;
ListClass<T>(Class<T> type) {
factory = new ObjectFactory(type);
}
static <T> ListClass<T> of(Class<T> type) {
return new ListClass<T>(type);
}
}
ListClass<GameObject> list =
ListClass.of(GameObject.class);
source to share
Citing docs on Class#getGenericSuperClass()
:
Corresponds to the type for the class that represents the superclass of the receiver class. For classes that represent base types, interfaces, and for java.lang.Object, the method is null.
Calling this class ObjectFactory<T>
will return a type Object
that is not ParameterizedType
.
source to share