getSimpleNameWithGenerics(Class <! - ? - > clazz)

时间:2011-01-16 18:01:12

标签: java generics reflection

我需要一个递归函数,它会打印一个类签名,包括类名和值类型参数。

MyNewClass&LT;串,列表与LT;整数&GT;,地图&LT;列表与LT;整数&GT;,字符串&GT;&GT; x = new MyNewClass&lt; ...&gt;(); Assert.assert(getSimpleNameWithGenerics(x).equals(“MyNewClass&lt; String,List&lt; Integer&gt;,Map&lt; List&lt; Integer&gt;,String&gt;&gt;”));

由于我是Java的新手,我很惊讶,不是在Java社区的任何地方找到这样的功能,也不能自己轻松地实现它。

这是我的尝试:

  

public static String getGenericClassSimpleName(Class&lt;?&gt; 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; 
     

}

,但最终会出现堆栈溢出(这就是为什么我决定在这里问一下,大声笑),碰到TypeVariable类......我从来没有找到方法来获得类型变量的真实“面孔”。

2 个答案:

答案 0 :(得分:0)

您必须拥有一个使用您感兴趣的类型的字段或方法,然后您可以“反思”它并查看所有通用详细信息。

或者你可以从Jackson中的类型捕获技术开始,然后从那里挖掘到支持它的库。

答案 1 :(得分:0)

类可以访问其类型参数,Fields参数和Method参数。我使用这段代码来提取实际的类型参数(它被简化 - “。get ...()[0]”,因为我只需要提取第一个类型参数。)

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

请参阅此课程:AEntityAccessor.javaPropertyAccessor.java,了解其如何用于提取地图参数。

这不是一个直接的答案,但我希望你会觉得这很有用。