获取泛型类.class对象



我正在绑定以保存通用值的类型,因为我无法在运行时获取它:

public class A<T> {
private final Class<T> genericType;
public A(Class<T> genericType) {
this.genericType = genericType;
}
public Class getGenericType() {
return genericType;
}
}

现在要制作子类,我按如下方式使用它:

public class B extends A<String> {
public B() {
super(String.class);
}
}

请注意,super(( 的参数类型与 A 的泛型类型匹配(通过编译时检查(。 这工作正常。但是如果我想用 Map 来拥有它,我无法获得正确的类对象:

public class C extends A<Map<String, String>> {
public C() {
super(Map.class); // does not match Map<String,String>
super(Map<String,String>.class) // no valid java expression, i dont know what 
}
}

所以有人得到提示来帮助我摆脱这种痛苦吗? 我目前能做的最好的事情就是放弃 A 中的强类型:

public class A<T> {
// old: private final Class<T> genericType;
private final Class genericType;  // note the missing generic
public A(Class genericType) {     // here as well
this.genericType = genericType;
}
public Class getGenericType() {
return genericType;
}
}

我不确定这是否满足您的要求,但您可以执行类似于 blow 的操作,请参阅如何获取 T 类型字段的类?

import java.lang.reflect.*;
import java.util.*;

public class GenericTypeTest{
public static void main(String []args){
B b = new B();
System.out.println("B is a " + b.getGenericType());
C c = new C();
System.out.println("C is a " + c.getGenericType());
}
}

class A<T> {
public Class getGenericType() {
Object genericType =  ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
if(genericType instanceof ParameterizedType){
genericType = ((ParameterizedType)genericType).getRawType();
}
return (Class<T>) genericType;
}
}

class B extends A<String> {
}
class C extends A<Map<String,String>> {
}

这将得到类似

B is a class java.lang.String
C is a interface java.util.Map

只有一个Class对象在运行时表示Map,您可以通过计算Map.class来获取。在运行时,没有单独的Class对象表示Map<String, String>Map<Integer, Integer>或其他任何内容。如果你只是想把通常有类型Class<Map>Map.class强制到Class<Map<String, String>>,你可以通过一些未经检查的强制转换来做到这一点:

super((Class<Map<String, String>>)(Class<?>)Map.class);

但是这是否会做你想要的取决于你期望对你没有显示的Class<T>genericType类型的变量做什么。例如,如果您将使用其.isInstance()方法来检查对象在运行时是否是T的实例,请知道由于我们在运行时不知道对象的泛型类型参数,因此我们只能检查对象的原始类型,而不是其类型参数。这就是为什么您可以执行foo instanceof Mapfoo instanceof Map<?>但不能执行foo instanceof Map<String, String>的原因相同。

或者,也许您想使用其.cast()方法在运行时对对象进行类型检查,如果该对象不是Class类的实例,通常会引发异常,如果是,则返回该对象,但编译时类型为T。但在这里,同样,您无法在运行时检查对象是否是参数化类型的实例,例如Map<String, String>;您只能检查它是否是Map.因此,通过它允许您在没有警告的情况下将结果作为类型T获取可能是不安全的,因为您将获得类型Map<String, String>的编译时表达式,但它可能真的是一个Map<Integer, Integer>。这与像(Map<String, String>)foo这样的未经检查的转换导致未选中的转换警告的原因相同。这是不安全的,可能会导致代码中其他位置出现意外问题。

最新更新