查看类型变量是否表示给定类的超类

时间:2016-01-29 21:00:29

标签: java reflection types casting

给出一个班级

class EnvironmentHolder<V> {
    protected Map<String,V> environment;

    // Get the Type of V via Google's GSon library; this part
    // works okay
    protected final Type VALUE_TYPE = new TypeToken<V>() {}.getType();

    ...

    public void importEnvironment(Class aClass) {
        // NEEDS AN IMPLEMENTATION
    }
}

其中V是某种引用类型,我正在尝试收集所有的引用类型 aClass的静态成员,可以“赋予”一类类型 V - 即那些是子类,实现或者 与V相同的班级。

我该怎么做?我想对importEnvironment使用以下实现:

for (Field field : aClass.getFields()) {
    ((Class) V).isAssignableFrom(field.getType())
}

我看到Class确实是Type的实施者,但我不是 确定如何安全地进行演员表演。 (Type也包括在内 非引用类型,不是Class es。)

注意:不要说,“类型擦除会妨碍在运行时执行此操作” 直到你想到了。相当多的问题都是一个几乎是自动的响应,这似乎意味着反射API无法在Java中实现。

谢谢!

1 个答案:

答案 0 :(得分:2)

由于类型擦除,您不能使用现有代码执行此操作:您不知道V在运行时是什么。

您需要Class<V>的实例,因此您可以说:

clazz.isAssignableFrom(field.getType());

您可以将其作为EnvironmentVariable<V>的构造时参数传递,也可以将其作为importEnvironment的另一个参数传递。我说前者更方便,因为你只需要做一次,而不是每当你调用importEnvironment时。

class EnvironmentHolder<V> {
    private final Class<V> clazz;

    EnvironmentHolder(Class<V> clazz) {
        this.clazz = clazz;
    }

    public void importEnvironment(Class<?> aClass) {
        for (Field field : aClass.getFields()) {
            if (clazz.isAssignableFrom(field.getType())) {
                // ...
            }
        }
    }
}

请注意,您也可以通过传入(并存储)TypeToken<V>的实例来执行此操作 - 如果V本身是通用类型,这可能会更方便。但是,正如@nickb所说,你实际上需要传入那个实例;你不能依靠泛型来创造它。

另请注意<?>上的Class<?> aClass - 此处没有理由使用原始类型。