繁体   English   中英

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

[英]Get generic field type at runtime via reflection

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

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() :返回值为T TypeVariableImpl
  • field.getType()返回Object

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

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

  1. 我实际上并不知道类型是泛型还是常规类型,我只知道它是用@id注释的。
  2. 我不知道这个字段位于类层次结构中的哪个位置。

这是我用来获取类层次结构中所有字段的方法。

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注释的字段,其中只有一个。

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

一种方法是知道泛型参数化类型的Class<T> entityClass类型,即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);
    }
}

使用TypeTools

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

干杯

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM