通过反射在运行时获取通用字段类型

时间:2015-10-13 10:19:24

标签: java reflection

我无法通过id的反射来访问MyClass的运行时类型。

public abstract class AbstractEntity<T> {

    @Id
    private T id; //I need to access the runtime class of T

}

public class MyClass extends AbstractEntity<Long> {} 

我正在使用java反射,并且可以访问超类中的id Field

我尝试使用:

  • field.getGenericType():返回TypeVariableImpl,其值为T
  • field.getType()返回Object

我想访问Long作为字段类型。

我正在为其他人编写一个库,但有一些问题:

  1. 我实际上并不知道该类型是泛型类型还是普通类型,我只知道它是用@id注释的。
  2. 我不知道这个字段位于类层次结构中的哪个位置。
  3. 这是我用来获取类层次结构中所有字段的方法。

    private Set<Field> getAllFields(final Object object) {
        final Set<Field> fields = new HashSet<>();
        fields.addAll(Arrays.asList(object.getClass().getDeclaredFields()));
        Class<?> superclass = object.getClass().getSuperclass();
        while (superclass != null) {
            fields.addAll(Arrays.asList(superclass.getDeclaredFields()));
            superclass = superclass.getSuperclass();
        }
        return fields;
    }
    

    然后,我将此列表过滤为注释为@Id的字段,其中只有一个。

2 个答案:

答案 0 :(得分:3)

在运行时,泛型不是具体化。这意味着信息在运行时不存在。

一种方法是知道通用参数化类型的类类型,即Class<T> entityClass

有几种方法可以实现这一目标。您可以拥有默认构造函数并反射获取类类型:

this.entityClass= (Class<T>) ((ParameterizedType) getClass()
                            .getGenericSuperclass()).getActualTypeArguments()[0];

或者创建一个构造函数,在构造函数上传递Generic类类型:

protected AbstractEntity(Class<T> entityClass) {
    this.entityClass = entityClass;
}

然后,您的具体实体类可以默认传递其类类型,如下所示:

public class MyClass extends AbstractEntity<Long> {

    public MyClass() {
        super(Long.class);
    }
}

答案 1 :(得分:0)

使用TypeTools

Type<?> t = TypeResolver.resolveRawArgument(AbstractEntity.class, MyClass.class);
assert t == Long.class

干杯