面试题答案
一键面试类型擦除概念
Java泛型中的类型擦除指的是,在编译阶段,所有的泛型类型信息都会被移除,只保留原生类型。编译器会在编译时根据泛型的类型参数进行类型检查和类型推断,并在适当的地方插入类型转换代码,但在运行时,这些泛型类型信息是不存在的。这是因为Java的泛型是通过编译器实现的,为了保持与Java 1.5之前版本的兼容性而采用的机制。
类型擦除在运行时对泛型代码产生的影响举例
-
无法在运行时获取泛型类型参数的实际类型
import java.util.ArrayList; import java.util.List; public class GenericTypeErasureExample { public static void main(String[] args) { List<String> stringList = new ArrayList<>(); List<Integer> integerList = new ArrayList<>(); // 运行时下面两个结果是一样的,都输出List.class System.out.println(stringList.getClass()); System.out.println(integerList.getClass()); } }
在上述代码中,虽然
stringList
是List<String>
类型,integerList
是List<Integer>
类型,但在运行时通过getClass()
方法获取到的都是List.class
,无法区分具体的泛型类型参数。这是因为类型擦除,运行时只知道它们是List
类型,而不知道具体的参数类型。 -
泛型方法和非泛型方法重载问题
public class OverloadWithGenerics { public static void method(List<String> list) { System.out.println("method(List<String> list)"); } // 下面这个方法在编译时会报错,因为类型擦除后两个方法的签名相同 // public static void method(List<Integer> list) { // System.out.println("method(List<Integer> list)"); // } public static void main(String[] args) { } }
由于类型擦除,
List<String>
和List<Integer>
在运行时都被擦除为List
,所以不能通过泛型类型参数来重载方法。如果同时定义这两个方法,编译器会报错,提示方法签名重复。这体现了类型擦除对方法重载的影响,在运行时无法根据泛型类型参数来区分方法。