获取具有Java反射的泛型类字段类型

获取具有Java反射的泛型类字段类型,java,generics,reflection,Java,Generics,Reflection,我的班级结构如下: public class GenClass<T> { public T elem; } 现在我需要一个函数来获取元素类: public class Test { public AClass<UUID, String> a; public BClass<Integer, Float> b; void do() throws Exception { Field aField = Test.cl

我的班级结构如下:

public class GenClass<T> {
    public T elem;
}
现在我需要一个函数来获取元素类:

public class Test {
    public AClass<UUID, String> a;
    public BClass<Integer, Float> b;

    void do() throws Exception {
        Field aField = Test.class.getField("a");
        Field bField = Test.class.getField("b");

        getType(aField, "elem"); // should return String.class
        getType(bField, "elem"); // should return Integer.class
    }

    Class<?> getType(Field f, String classField) {
        // ???
    } 
}
公共类测试{
公共a类;
公共b类;
void do()引发异常{
Field aField=Test.class.getField(“a”);
字段bField=Test.class.getField(“b”);
getType(aField,“elem”);//应返回String.class
getType(bField,“elem”);//应返回Integer.class
}
类getType(字段f,字符串类字段){
// ???
} 
}

我需要如何实现
getType
以获得所需的结果?

通过调用
getGenericType
,您拥有了与字段
数据
对应的
Type
对象

Type t = f.getGenericType();  // f is your Field
ParameterizedType pt = (ParameterizedType) t;
和它的实现代表了这里可能出现的类型的不同情况。因为
数据
的类型是
GenClass
,使用类型参数进行参数化,所以这里返回的
类型实际上是
参数化类型

Type t = f.getGenericType();  // f is your Field
ParameterizedType pt = (ParameterizedType) t;
通常可能有多个泛型类型参数,但这里只有一个。打电话

是的,我们有另一个
类型
实例,但是这个实例表示
字段
的泛型类型参数,而不是
字段
本身。因为您在
测试
类中提供了一个类类型,所以这个
类型
只不过是一个普通的
--
UUID.class

System.out.println(parameter instanceof Class);
System.out.println(parameter == UUID.class);
输出:

true
true

好的,那么您需要做的是获取a/b字段的原始类型上的类型参数和ParameteredType上的实际类型参数。然后,可以将raw type参数与您感兴趣的A/b类上的elem字段匹配,但随后可以使用该字段解析/匹配实际类型(数组排列)


检查,但我不知道,字段的哪个实际类型参数用于elem。也许我有一个像AClass这样的类,然后声明
B data
。我怎么知道,数据是第三种类型的参数?请看我编辑的问题,以更好地解释我的问题!
true
true
public class TestGenerics {
    public AClass<UUID, String> a;
    public BClass<Integer, Float> b;

    void getFieldTypes() throws NoSuchFieldException, SecurityException {
        Field aField = TestGenerics.class.getField("a");
        Field bField = TestGenerics.class.getField("b");

        Class<?> aFieldElem = getType(aField, "elem"); // should return String.class
        Class<?> bFieldElem = getType(bField, "elem"); // should return Integer.class

        System.out.println("a field, elem field type: " + aFieldElem.getSimpleName());
        System.out.println("b field, elem field type: " + bFieldElem.getSimpleName());
    }

    Class<?> getType(final Field f, final String classField) throws NoSuchFieldException, SecurityException {
        Type genericType = f.getGenericType();
        //going to assume this. In reality you'd want to do an instanceof first
        ParameterizedType pt = (ParameterizedType) genericType;
        Class<?> rawType = (Class<?>) pt.getRawType();
        Type[] actualTypeParams = pt.getActualTypeArguments();
        TypeVariable<?>[] rawTypeParams = rawType.getTypeParameters();

        Field classFieldOnF = rawType.getField(classField);

        genericType = getResolvedType(classFieldOnF.getGenericType(), rawTypeParams, actualTypeParams);

        //same here, you'd need to do an instanceof first
        return (Class<?>) genericType;
    }

    private Type getResolvedType(final Type genericType, final Type[] rawTypeParams, final Type[] actualTypes) {
        for (int i = 0; i < rawTypeParams.length; i++) {
            if (genericType == rawTypeParams[i]) return actualTypes[i];
        }
        return genericType;
    }

    public static void main(final String[] args) throws NoSuchFieldException, SecurityException {
        TestGenerics test = new TestGenerics();
        test.getFieldTypes();
    }
}
a field, elem field type: String
b field, elem field type: Integer