为何Test<?>实例的构造方法可接受非null对象?
为什么
Test<?>实例可以通过带String参数的构造方法初始化,却不能调用set(String)? 核心原因在于构造实例的类型推断和通配符变量的类型限制是两个独立的阶段:
构造时的明确类型推断
当你写new Test<>("Test")时,编译器会根据传入的String参数自动推断出这个新实例的泛型参数是String,也就是实际创建的是Test<String>对象,和显式写new Test<String>("Test")完全等价。通配符变量的赋值兼容性
Test<?>代表任意泛型参数的Test实例,它是所有Test<T>的父类型。所以Test<String>对象可以安全赋值给Test<?>变量,这和String对象能赋值给Object变量的逻辑一致,完全符合Java的类型规则。
而调用set("Test")报错的逻辑是:
当变量类型为Test<?>时,编译器只知道它的泛型参数是某个未知类型,但无法确定具体是什么。此时调用set(T)方法,编译器无法验证传入的String是否和这个未知类型兼容——毕竟这个未知类型可能是Integer、Double等任意类型,所以除了null(所有类型都兼容null),传任何具体类型的参数都会触发编译错误。
简单总结:
- 构造出来的是明确的
Test<String>实例,只是被“向上转型”成了Test<?>类型的变量 - 但
Test<?>类型的变量无法确定自身泛型参数的具体类型,因此无法安全写入除null外的任何数据
内容的提问来源于stack exchange,提问作者Giorgos
相关产品推荐
相关产品推荐

