面试题答案
一键面试类型擦除概念
Java泛型中的类型擦除是指在编译阶段,所有的泛型类型信息都会被擦除掉,只保留原始类型。编译器在编译时会将泛型类型替换为它们的限定类型(如果有上限限定,否则替换为Object
),并且在运行时,Java虚拟机(JVM)并不知道泛型的存在。这一机制使得Java泛型能够在不改变字节码格式的前提下实现泛型功能,保持了与Java旧版本的兼容性。
代码示例
import java.util.ArrayList;
import java.util.List;
public class TypeErasureExample {
public static void main(String[] args) {
List<String> stringList = new ArrayList<>();
stringList.add("Hello");
List<Integer> integerList = new ArrayList<>();
integerList.add(123);
printList(stringList);
printList(integerList);
}
public static void printList(List list) {
for (Object element : list) {
System.out.println(element);
}
}
}
在上述代码中:
- 定义了
stringList
和integerList
两个不同泛型类型的列表。 printList
方法接受一个原始类型的List
参数。这是因为在编译后,List<String>
和List<Integer>
的泛型信息被擦除,都变成了原始类型List
。- 在
printList
方法中,通过遍历List
输出元素,这表明在运行时,JVM无法区分List<String>
和List<Integer>
,因为泛型信息已经被擦除。
可能带来的影响
- 编译时类型检查:虽然泛型在编译时提供了强大的类型检查功能,但类型擦除意味着运行时无法获取泛型的实际类型。这可能导致一些潜在的错误,例如在反射操作中,如果依赖泛型类型信息,可能会遇到问题。
- 无法创建泛型数组:由于类型擦除,无法直接创建泛型数组,例如
T[] array = new T[10];
是不允许的。因为编译后T
会被擦除,无法确定数组元素的实际类型。 - 桥接方法:在泛型继承和重写方法时,编译器可能会生成桥接方法来保持多态性。这是因为擦除后父类和子类方法的签名可能变得相同,桥接方法可以解决这一冲突,但也增加了字节码的复杂性。