getSimpleNameWithGenerics(Class<?> clazz)
I need a recursive function, that would print a class signature, including class name and values uf type parameters.
MyNewClass< String,List< Integer>,Map< List< Integer>,String>> x = new MyNewClass<...>(); Assert.assert(getSimpleNameWithGenerics(x).equals("MyNewClass< String,List< Integer>,Map< List< Integer>,String>>"));
Since I'm a newbie in Java, I was quite surprised, not to find such function anywhere around Java community, nor to be able to implement it easily myself.
Here is my try:
public static String getGenericClassSimpleName(Class< ?> c) {
String s = c.getSimpleName(); TypeVariable[] tv = c.getTypeParameters(); for(int i = 0; i < tv.length; i++) { s += i == 0 ? "<" : ","; s += getGenericClassSimpleName(tv[i].getGenericDeclaration().getClass()); } if(tv.length > 0) s += ">"; return s;
}
, but it ends up with sta开发者_如何学Cck overflow (that's why I decided to ask here, lol), bumping the TypeVariable class... I never found the way to get to real "faces" of the type variables.
You have to have a field or a method that uses the type you are interested in, and then you can 'reflect' upon it and see all the generic details.
Or you can start from the type capture technology in Jackson and dig down from there to the library that supports it.
class can have access to its type parameters, Fields parameters and Method parameters. I use this piece of code to extract actual type parameters (it is simplified -".get...()[0]" since I only have a need to extract first type parameter).
private Class extractClass(Type type) {
Class result = null;
if (type instanceof Class)
result = (Class) type;
if (type instanceof WildcardType) {
if (((WildcardType) type).getLowerBounds().length > 0) {
result = extractClass(((WildcardType) type).getLowerBounds()[0]);
} else if (((WildcardType) type).getUpperBounds().length > 0) {
result = extractClass(((WildcardType) type).getUpperBounds()[0]);
}
} else if (type instanceof ParameterizedType) {
result = extractClass(((ParameterizedType) type).getActualTypeArguments()[0]);
} else if (type instanceof TypeVariable) {
TypeVariable tv = (TypeVariable) type;
Class c = getEntityClass();
result = extractTypeVariableBounds(tv, c);
if (result == null)
result = extractTypeVariableBounds(tv, (Class) tv.getGenericDeclaration());
if (result == null && tv.getBounds().length > 0)
result = extractClass(tv.getBounds()[0]);
}
return result;
}
private Class extractTypeVariableBounds(TypeVariable tv, Class c) {
if (c == null)
return Object.class;
Type genericSuperclass = c.getGenericSuperclass();
if (genericSuperclass != null) {
int index = 0;
for (TypeVariable dtv : c.getSuperclass().getTypeParameters()) {
if (dtv.equals(tv)) {
while (genericSuperclass instanceof Class) {
genericSuperclass = ((Class) genericSuperclass).getGenericSuperclass();
}
if (genericSuperclass != null)
return extractClass(((ParameterizedType) genericSuperclass).getActualTypeArguments()[index]);
}
index++;
}
c = c.getSuperclass();
return extractTypeVariableBounds(tv, c.getSuperclass());
}
if (tv.getBounds().length > 0)
return extractClass(tv.getBounds()[0]);
return Object.class;
}
See this class: AEntityAccessor.java and PropertyAccessor.java to see how its used to extract Map parameters.
it's not a direct answer but still, I hope You will find this useful.
精彩评论