Hi, I got a
java.lang.ClassCastException:
sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl cannot be cast to
java.lang.Class
at thewebsemantic.ValuesContext.getGenericType(ValuesContext.java:69)
When using field that's type is a List of generic types. I changed the code to
the following to make it work:
public Class<?> getGenericType(final ParameterizedType type) {
// unfortunately we don't have the TypeVariable information from the reference to this type,
// so some TypeVariable->Type mappings are missing
final Map<TypeVariable<?>, Type> typeVariableMap = new HashMap<TypeVariable<?>, Type>();
final Type actualType = type.getActualTypeArguments()[0];
return getClassForType(actualType, typeVariableMap);
}
public Class<?> getGenericType(final ParameterizedType type, final HashMap<TypeVariable<?>, Type> typeVariableMap) {
final Type actualType = type.getActualTypeArguments()[0];
return getClassForType(actualType, typeVariableMap);
}
private Class<?> getClassForType(final Type type, final Map<TypeVariable<?>, Type> typeVariableMap) {
if (type == null) {
return NullType.class;
}
if(type instanceof Class) {
return (Class<?>)type;
}
if(type instanceof ParameterizedType) {
final Type rawType = ((ParameterizedType) type).getRawType();
return getClassForType(rawType, typeVariableMap);
}
if(type instanceof GenericArrayType) {
final Type genericType = ((GenericArrayType) type).getGenericComponentType();
// find class object of type the array is of
final Class<?> arrayClass = getClassForType(genericType, typeVariableMap);
// didn't find another way to get Class for array of type arrayClass
return Array.newInstance(arrayClass, 0).getClass();
}
if(type instanceof TypeVariable<?>) {
final Type actualType = typeVariableMap.get(type);
// if we don't have mapping to actual type, we use most global class Object.class
if(actualType == null) {
return Object.class;
}
return getClassForType(actualType,typeVariableMap);
}
// don't know how to handle WildcardType and TypeVariable
throw new IllegalArgumentException();
}
public Map<TypeVariable<?>, Type> getGenericTypeMap(final Type type) {
final Map<TypeVariable<?>, Type> result = new HashMap<TypeVariable<?>, Type>();
findTypeVariableMappingsRecursive(type, result);
return result;
}
private void findTypeVariableMappingsRecursive(final Type type, final Map<TypeVariable<?>, Type> typeVariableMap) {
// mappings for current type
findTypeVariableMappings(type, typeVariableMap);
// now mappings for supertypes and generic interfaces
if(type instanceof Class<?>) {
final Class<?> clazz = (Class<?>) type;
final Type superType = clazz.getGenericSuperclass();
if(superType != null) {
findTypeVariableMappingsRecursive(superType,typeVariableMap);
}
final Type[] interfaceTypes = clazz.getGenericInterfaces();
for (Type interfaceType : interfaceTypes) {
findTypeVariableMappingsRecursive(interfaceType, typeVariableMap);
}
}
}
private void findTypeVariableMappings(final Type type,
final Map<TypeVariable<?>, Type> map) {
if (type instanceof ParameterizedType) {
final ParameterizedType parameterizedType = (ParameterizedType) type;
final GenericDeclaration genericDeclaration = (GenericDeclaration) parameterizedType.getRawType();
final TypeVariable<?>[] typeVariables = genericDeclaration.getTypeParameters();
final Type[] actualTypes = parameterizedType.getActualTypeArguments();
for (int i = 0; i < actualTypes.length; ++i) {
map.put(typeVariables[i], actualTypes[i]);
}
}
}
I did also add support for generic arrays, although the framework do not seem
to support arrays at the moment. Unfortunately the caller does not (and maybe
cannot) provide information which TypeVariables are mapped to which actual
types, or a ParameterizedType this information can be read from. I added
methods for retrieving this information from a Type (see getGenericTypeMap).
Original issue reported on code.google.com by maxbur...@googlemail.com on 8 Jun 2012 at 1:58
Original issue reported on code.google.com by
maxbur...@googlemail.com
on 8 Jun 2012 at 1:58