MST

星途 面试题库

面试题:Java泛型之类型擦除

请阐述Java泛型中类型擦除的概念,并举例说明类型擦除在运行时对泛型代码产生的影响。
12.7万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

类型擦除概念

Java泛型中的类型擦除指的是,在编译阶段,所有的泛型类型信息都会被移除,只保留原生类型。编译器会在编译时根据泛型的类型参数进行类型检查和类型推断,并在适当的地方插入类型转换代码,但在运行时,这些泛型类型信息是不存在的。这是因为Java的泛型是通过编译器实现的,为了保持与Java 1.5之前版本的兼容性而采用的机制。

类型擦除在运行时对泛型代码产生的影响举例

  1. 无法在运行时获取泛型类型参数的实际类型

    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());
        }
    }
    

    在上述代码中,虽然 stringListList<String> 类型,integerListList<Integer> 类型,但在运行时通过 getClass() 方法获取到的都是 List.class,无法区分具体的泛型类型参数。这是因为类型擦除,运行时只知道它们是 List 类型,而不知道具体的参数类型。

  2. 泛型方法和非泛型方法重载问题

    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,所以不能通过泛型类型参数来重载方法。如果同时定义这两个方法,编译器会报错,提示方法签名重复。这体现了类型擦除对方法重载的影响,在运行时无法根据泛型类型参数来区分方法。