Java泛型类以非泛型方式使用时字段泛型信息会丢失?规范有说明吗?
Java泛型原始类型的类型擦除规则解析
你观察到的这个现象完全符合Java泛型的**原始类型(Raw Type)**规则,Java语言规范里对此有明确的定义。
核心规则说明
当你使用泛型类的原始类型(比如代码里的Test而不是Test<T>、Test<?>这类带泛型参数的形式)时,Java规范明确规定:
原始类型会擦除该类及其所有成员的泛型信息——不仅是类本身声明的类型参数(比如
Test<T>里的<T>),类内部定义的任何泛型成员(比如你的List<String>)都会被擦除到对应的原始类型。
结合代码实例分析
- 在
method1中,参数是Test test(原始类型),所以test.list的类型会被擦除为List(而非List<String>)。编译器无法确定列表元素的具体类型,只能默认是Object,因此用String value接收会触发编译错误,必须用Object来接收遍历元素。void method1(Test test) { for (String value : test.list) { // 编译错误:原始类型擦除了List<String>的泛型信息 } // 正确写法:只能用Object接收 for (Object value : test.list) { } } - 在
method2中,参数是Test<?> test(通配符泛型类型,不属于原始类型),此时类内部的泛型成员List<String>的类型信息会被保留。编译器明确知道list的元素是String,因此可以直接用String value接收遍历元素,不会有编译错误。void method2(Test<?> test) { // 正确写法:泛型信息被保留,编译器确认元素是String for (String value : test.list) { } }
额外提示
原始类型的设计初衷是为了兼容Java 5之前没有泛型的老代码,但它会完全丢失泛型的类型安全检查,所以在现代Java开发中,除非是必须兼容遗留代码的场景,否则不建议使用原始类型,优先使用带泛型参数的形式(比如Test<?>、Test<String>等)。
内容的提问来源于stack exchange,提问作者Yang Lifan
相关产品推荐
相关产品推荐

