我正在绑定以保存通用值的类型,因为我无法在运行时获取它:
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 Map
或foo 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
这样的未经检查的转换导致未选中的转换警告的原因相同。这是不安全的,可能会导致代码中其他位置出现意外问题。