相等。new ArrayList<Integer>().getClass() == new ArrayList<Float>().getClass() 结果为 true,二者都是 ArrayList.class

原因是类型擦除:Java 泛型只在编译期存在,编译器完成类型检查后会擦除泛型实参,字节码中 ArrayList 只有一个原始类型(raw type),类型参数的位置被替换为其上界(无界时为 Object),需要的地方再插入强制转型。运行期 JVM 根本无从区分 ArrayList<Integer>ArrayList<Float>,getClass() 返回的是同一个 Class 对象。

System.out.println(new ArrayList<Integer>().getClass()
        == new ArrayList<Float>().getClass()); // true

类型擦除带来一系列推论:不能用泛型类型参数创建实例(new T())、不能创建泛型数组、instanceof 不能带泛型实参、静态成员不能引用类的类型参数、重载 foo(List<String>)foo(List<Integer>) 擦除后签名相同而编译失败。

追问方向:为什么 Java 选择擦除而不是具化(reified)泛型?(兼容旧代码与共享字节码)如何在运行期拿到泛型信息?(getGenericSuperclass、TypeReference 技巧)

(约 340 字)