面试题答案
一键面试类型擦除概念
Java泛型中的类型擦除指的是,在编译阶段,所有的泛型类型信息都会被擦除,替换为它们的原生类型(raw type)。编译器会在编译时进行泛型类型检查,并在必要的地方插入类型转换代码。这意味着在运行时,Java虚拟机(JVM)并不知道泛型的具体类型信息。
对编译和运行的影响
- 编译时:编译器根据泛型类型信息进行类型检查,确保类型安全。例如,定义一个泛型方法
public static <T> void add(List<T> list, T item)
,如果调用add(new ArrayList<Integer>(), "string")
,编译器会报错,因为类型不匹配。 - 运行时:由于类型擦除,运行时无法获取泛型的具体类型。这可能导致一些潜在问题,比如在使用反射时。
泛型类实例化的例子
定义泛型类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
(原生类型)。它们在运行时的行为特点如下:
- 内存布局:从内存角度看,
intGenericClass
和stringGenericClass
的对象布局是一样的,因为类型擦除后没有类型参数的区别。 - 方法调用:调用
getValue
方法时,编译器会在调用处插入类型转换代码。对于intGenericClass.getValue()
,编译器会插入(Integer)
转换;对于stringGenericClass.getValue()
,编译器会插入(String)
转换。所以在运行时,根据插入的类型转换代码来获取正确类型的值。但如果插入的转换与实际对象类型不匹配,会抛出ClassCastException
。