getClass().getName()为何能返回泛型类型的类名?
解惑:Java泛型类型擦除后,getClass()为何能返回实际泛型类型?
这问题真的很典型,很多刚接触泛型的开发者都会在这里绕弯子。咱们一步步理清楚:
首先,你得明确Java泛型的类型擦除到底擦的是什么:
- 类型擦除是针对泛型类/方法的类型参数本身,在编译完成后,
Gen<T>里的T会被替换成它的默认上界Object(如果没指定其他上界的话)。也就是说,JVM在运行时根本不知道Gen曾经被指定过String这个类型参数。 - 但!你传入
Gen构造方法的那个"abcd"对象,它本身是一个实实在在的String实例,Java中所有对象的运行时类型信息都是保留的,不会因为泛型擦除而丢失。
再看你的代码:
public class Gen<T> { T ob; public Gen(T ob) { this.ob=ob; } void showType() { System.out.println("Type of T is " + ob.getClass().getName()); } } public class GenDemo { public static void main(String[] args) { Gen<String> str = new Gen("abcd"); str.showType(); } }
输出:
Type of T is java.lang.String
你调用的ob.getClass(),本质上是在问存储在ob变量里的那个实际对象的运行时类型,而不是在问泛型参数T的类型。因为ob引用的是一个String对象,所以getClass()自然返回String的Class对象,这和泛型类型擦除完全不矛盾。
举个反例你就更清楚了:如果尝试直接获取T的Class,比如在Gen类里写T.class,编译器会直接报错——因为类型擦除后,T这个符号在运行时已经不存在了,JVM根本不知道它是什么。但通过实际对象获取类型,是完全合法且符合预期的。
总结一下:泛型类型擦除擦的是泛型参数的类型信息,而不是实际对象的类型信息,你代码里的getClass()是在操作实际对象,所以能拿到真实的类型名。
内容的提问来源于stack exchange,提问作者Arjun
相关产品推荐
相关产品推荐

