Java泛型疑问:通配符<?>、Object与泛型类共同父类的差异
这两处描述其实没有矛盾,只是分别对应泛型的运行时擦除特性和编译时类型体系两个不同层面:
「任意两个泛型类的共同父类是Object」指的是运行时的实际类。Java泛型基于类型擦除实现,编译后所有带泛型参数的类型都会被擦除成原始类型——比如
List<Integer>和List<String>运行时都是List类,而所有Java类的最终父类都是Object,所以从运行时的类继承关系看,它们的共同父类确实是Object。「
List<Integer>与List<String>的共同父类是List<?>」指的是编译时的类型兼容性。在编译期的类型系统里,List<?>是所有具体泛型参数List的超类型,它代表“任意类型元素的List”,所以从编译时的类型赋值、类型检查角度,List<Integer>和List<String>都可以向上转型为List<?>,此时List<?>是它们在编译类型体系中的共同超类型。
你测试得到父类是Object的原因是:你获取的是运行时的类信息(比如调用getClass()方法),泛型参数在运行时已经被擦除,所以TempFruitHolder<Integer>.getClass()和TempFruitHolder<String>.getClass()返回的都是TempFruitHolder.class,List<Integer>.getClass()返回的是List.class,这些原始类的父类自然是Object。
举个直观的例子:
编译时你可以写:
List<Integer> intList = new ArrayList<>(); List<?> wildcardList = intList; // 合法,编译通过
但运行时执行intList.getClass() == wildcardList.getClass()会返回true,因为它们都是ArrayList类的实例,而ArrayList的父类链最终指向Object。
内容的提问来源于stack exchange,提问作者user16422658

