为何Integer列表可存储打印String?赋值无异常原因解析
为啥Java里String列表能“装”进Integer列表还不报错?
这事儿核心原因就是Java泛型的类型擦除——这可是Java泛型最容易让人踩坑的特性!咱们一步步拆解你的代码:
1. 编译时:泛型是“语法糖”,编译后全变原始类型
Java的泛型只在编译阶段生效,编译完成后,所有泛型信息都会被擦除。也就是说:
List<String>、List<Integer>编译后都会变成原始类型List- 你写的
List raw = abc;和List<Integer> def = raw;,在编译器眼里,本质都是把List类型的引用赋值给另一个List类型的变量,所以只会给你一个“未经检查的转换”警告,但不会抛出编译错误。
2. 运行时:底层存的都是Object引用
不管你泛型声明的是啥类型,ArrayList底层的数组都是Object[]类型。你调用abc.add("something")时,其实是把String对象的引用存在了Object[]里。
当你把这个列表赋值给def(List<Integer>)后,底层存储的对象根本没变——还是那个String引用。
3. 为啥System.out.println(def.get(0))没报错?
这里关键在于println方法的参数是Object类型,def.get(0)返回的对象(虽然你声明的是Integer)不需要做强制类型转换就能传给println。如果换个写法:
Integer num = def.get(0); // 这里运行时会直接抛出ClassCastException!
因为编译器会自动在这行代码里插入(Integer)的强制转换,运行时发现实际是String类型,转换失败就炸了。
简单总结:泛型只在编译时帮你做类型检查,运行时根本不知道你声明的泛型类型;底层存储的都是Object,只要不触发跨类型的强制转换,就不会报错——但这种写法是极度危险的,很容易在后续代码里埋坑!
内容的提问来源于stack exchange,提问作者Soham Banerjee
相关产品推荐
相关产品推荐

