MST

星途 面试题库

面试题:Java泛型中类型擦除的基本原理是什么

请阐述Java泛型在编译阶段类型擦除的具体过程,例如List<Integer>在类型擦除后变成了什么,以及这对泛型代码的运行会产生怎样的影响?
34.1万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

1. Java泛型在编译阶段类型擦除的具体过程

  • 基本规则:Java泛型是在编译期实现的,编译器在编译时会进行类型擦除。具体来说,编译器会将泛型类型替换为其上限(如果指定了上限,默认上限是Object)。
  • 泛型类型参数的擦除:对于泛型类class Generic<T> {},在编译后,类型参数T会被擦除,实际类型变成Object。例如,List<Integer>中的Integer类型参数会被擦除。
  • 泛型方法的擦除:对于泛型方法public <T> void method(T t) {},编译后类型参数T也会被擦除,方法变为public void method(Object t) {}。如果泛型方法指定了上限public <T extends Number> void method(T t) {},擦除后变为public void method(Number t) {}

2. List<Integer>在类型擦除后变成了什么

List<Integer>在类型擦除后变成了List,即原始类型。具体来说,所有对Integer类型的引用都被替换为对Object类型的引用。例如,原本获取List<Integer>中元素的代码Integer num = list.get(0);,在擦除后实际执行的代码类似Object obj = list.get(0); Integer num = (Integer) obj;

3. 对泛型代码运行的影响

  • 优点
    • 向后兼容性:由于类型擦除,Java泛型可以与旧版本的Java代码(没有泛型)兼容。这使得在引入泛型的同时,已有的代码库无需进行大规模修改就能继续使用。
    • 性能无损耗:在运行时没有额外的类型信息,因此不会因为泛型而增加运行时的开销。
  • 缺点
    • 运行时类型检查缺失:由于类型信息在编译期被擦除,运行时无法获取泛型的实际类型。例如,List<Integer>List<String>在运行时是同一个类型,这可能导致在运行时出现ClassCastException。如果向一个List<Integer>中错误地添加了一个String对象(绕过编译器检查的情况下),在获取元素并强制转换为Integer时就会抛出异常。
    • 无法创建泛型数组:因为类型擦除,new T[]这种创建泛型数组的操作是不允许的。例如List<Integer>[] listArray = new List<Integer>[10];是不合法的,只能使用List[] listArray = new List[10];,但这样就失去了泛型的类型安全性。