泛型与类型擦除
面试官问:"Java 泛型的类型擦除是什么?"
候选人小何答:"泛型信息在编译后会被擦除,运行时不保留。"
面试官追问:"那 List<String> 和 List<Integer> 在运行时的 Class 对象是什么?"
小何说:"都是 List,不带泛型参数。"
面试官又问:"那为什么 new ArrayList<String>() 不能 add(Integer)?"
小何卡住了。
【面试官心理】 类型擦除是 Java 泛型的核心机制,但大多数人只知道"编译后擦除"这个结论,不知道具体是怎么擦除的、擦除后发生了什么。能说出"桥接方法"和"类型检查点"的候选人,才是真正理解过泛型实现的人。
一、类型擦除的本质 🔴
1.1 擦除前 vs 擦除后
编译后(类型擦除):
1.2 类型擦除的两种情况
1.3 擦除后的类型检查
类型检查发生在编译期,而不是运行期。
二、泛型与多态的矛盾 🔴
2.1 子类泛型的类型不一致
2.2 桥接方法的必要性
💡
能用字节码工具看到"桥接方法"的候选人,面试官会认为有深入研究。这是 P6+ 的加分点。
三、泛型的局限 🔴
3.1 不能用基本类型
原因:类型擦除后变成 Object,基本类型不是对象,无法对应。
3.2 不能 new 泛型数组
3.3 不能实例化泛型类型
3.4 不能用 instanceof
3.5 不能重载方法签名相同但泛型参数不同的方法
四、泛型与数组 🔴
4.1 不能创建泛型数组
⚠️
泛型数组的原始类型是类型安全隐患。生产中如果看到这种代码,需要 review 确保不会有类型安全问题。
五、生产避坑
5.1 泛型擦除导致的 ClassCastException
5.2 Jackson 序列化泛型问题
六、追问升级
面试官:"List<Object> 和 List<String> 是什么关系?"
面试官:"泛型的应用场景有哪些?"
【面试官心理】
能说出"协变性"和"类型安全"作为 List<Object> 和 List<String> 不能赋值的原因,说明候选人对泛型的设计哲学有深入理解。这是 P6 的进阶点。