MST

星途 面试题库

面试题:Java泛型中的类型擦除机制及对代码的影响

请阐述Java泛型中类型擦除的概念,并举例说明它是如何影响泛型代码的编译和运行的。例如,在定义一个泛型类`GenericClass<T>`并使用不同具体类型实例化时,类型擦除后这些实例在运行时的行为有什么特点?
42.1万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

类型擦除概念

Java泛型中的类型擦除指的是,在编译阶段,所有的泛型类型信息都会被擦除,替换为它们的原生类型(raw type)。编译器会在编译时进行泛型类型检查,并在必要的地方插入类型转换代码。这意味着在运行时,Java虚拟机(JVM)并不知道泛型的具体类型信息。

对编译和运行的影响

  1. 编译时:编译器根据泛型类型信息进行类型检查,确保类型安全。例如,定义一个泛型方法public static <T> void add(List<T> list, T item),如果调用add(new ArrayList<Integer>(), "string"),编译器会报错,因为类型不匹配。
  2. 运行时:由于类型擦除,运行时无法获取泛型的具体类型。这可能导致一些潜在问题,比如在使用反射时。

泛型类实例化的例子

定义泛型类GenericClass<T>

public class GenericClass<T> {
    private T value;

    public GenericClass(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }
}

实例化GenericClass

GenericClass<Integer> intGenericClass = new GenericClass<>(10);
GenericClass<String> stringGenericClass = new GenericClass<>("Hello");

在类型擦除后,GenericClass<Integer>GenericClass<String>在运行时实际上都是GenericClass(原生类型)。它们在运行时的行为特点如下:

  • 内存布局:从内存角度看,intGenericClassstringGenericClass的对象布局是一样的,因为类型擦除后没有类型参数的区别。
  • 方法调用:调用getValue方法时,编译器会在调用处插入类型转换代码。对于intGenericClass.getValue(),编译器会插入(Integer)转换;对于stringGenericClass.getValue(),编译器会插入(String)转换。所以在运行时,根据插入的类型转换代码来获取正确类型的值。但如果插入的转换与实际对象类型不匹配,会抛出ClassCastException