还有其他相关问题,例如6624113,3403909,4516891但我的问题更简单,更具体。
我想在运行时知道我的类参数化了什么类型 - 我想要一个类型参数类型的Class对象。由于类型擦除,表达式T.class
不起作用,并且在C#中没有像typeof(T)
这样的函数来获取它。
但是,通过ParameterizedType和相关课程可以获得一些“超级反思”,这几乎可以解决所有问题。
import java.lang.reflect.ParameterizedType;
public class MyClass<T> {
public static void main( String[] args ) {
new MyClass<Integer>().printTypeParam();
}
public void printTypeParam() {
class DummyT extends MyClass<T> {}
class DummyString extends MyClass<String> {}
ParameterizedType ptT =
((ParameterizedType) DummyT.class.getGenericSuperclass() );
ParameterizedType ptString =
((ParameterizedType) DummyString.class.getGenericSuperclass() );
System.out.println( "DummyT: " + ptT + " " + ptT.getActualTypeArguments()[0] );
System.out.println( "DummyString: " + ptString + " " + ptString.getActualTypeArguments()[0] );
}
}
当我运行上面的内容时,我看到了这个输出:
DummyT: MyClass<T> T
DummyString: MyClass<java.lang.String> class java.lang.String
正如您所看到的,这适用于在编译时在包含对getGenericSuperClass
的调用的代码行中已知类型参数,但是在该调用本身处理泛型的情况下,它只是打印名称类型参数。
我有没有办法让第一行打印java.lang.Integer
而不是T
?
答案 0 :(得分:3)
你不能,简单明了。 Integer
未定义,完全是erased。如果您不相信我,请使用Integer
将文件编译一次,使用Long
编译一次。这两个二进制类文件绝对相同。
类型擦除是一个残酷的现实,你将无法绕过。我建议你重新考虑为什么你需要它,而不是采用hacks来试图避免它。
有用的AngelikaLanger Generics FAQ主题: