MST

星途 面试题库

面试题:Java泛型类型擦除带来的误区及解决方案

由于Java泛型的类型擦除机制,会导致一些使用上的误区。请举例说明至少2种因为类型擦除产生的误区,并提出相应的解决方案。
39.4万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

误区一:在运行时无法获取泛型类型信息

  1. 举例
    public class GenericTest<T> {
        private T value;
        public void setValue(T value) {
            this.value = value;
        }
        public T getValue() {
            return value;
        }
        public static void main(String[] args) {
            GenericTest<Integer> intTest = new GenericTest<>();
            intTest.setValue(10);
            // 这里无法在运行时获取到泛型参数T是Integer类型
            // 因为类型擦除,运行时T被擦除为Object
            Class<?> type = intTest.getClass().getGenericSuperclass();
            System.out.println(type);
        }
    }
    
  2. 解决方案
    • 可以通过传递Class对象的方式来获取类型信息。修改代码如下:
    public class GenericTest<T> {
        private T value;
        private Class<T> type;
        public GenericTest(Class<T> type) {
            this.type = type;
        }
        public void setValue(T value) {
            this.value = value;
        }
        public T getValue() {
            return value;
        }
        public static void main(String[] args) {
            GenericTest<Integer> intTest = new GenericTest<>(Integer.class);
            intTest.setValue(10);
            Class<?> type = intTest.type;
            System.out.println(type);
        }
    }
    

误区二:泛型数组创建问题

  1. 举例
    public class GenericArrayTest {
        public static void main(String[] args) {
            // 以下代码会编译错误
            // 因为类型擦除,无法创建泛型数组
            // List<String>[] listArray = new ArrayList<String>[10];
        }
    }
    
  2. 解决方案
    • 可以使用ArrayList等集合来代替泛型数组,或者创建通配符数组然后进行强制类型转换(但需要谨慎使用,因为存在类型安全风险)。例如:
    @SuppressWarnings("unchecked")
    public class GenericArrayTest {
        public static void main(String[] args) {
            Object[] objectArray = new Object[10];
            List<String>[] listArray = (List<String>[]) objectArray;
            // 使用时需注意类型安全,避免运行时错误
        }
    }
    

误区三:泛型方法重载问题

  1. 举例
    public class GenericOverloadTest {
        public static <T> void print(T t) {
            System.out.println("普通泛型方法:" + t);
        }
        // 以下方法编译错误,因为类型擦除后,两个方法签名相同
        // public static <E> void print(E e) {
        //     System.out.println("另一个普通泛型方法:" + e);
        // }
        public static void main(String[] args) {
            print("Hello");
        }
    }
    
  2. 解决方案
    • 改变方法签名,例如增加参数或者修改返回类型等。比如:
    public class GenericOverloadTest {
        public static <T> void print(T t) {
            System.out.println("普通泛型方法:" + t);
        }
        public static <E> int print(E e, int num) {
            System.out.println("另一个泛型方法:" + e);
            return num;
        }
        public static void main(String[] args) {
            print("Hello");
            print("World", 10);
        }
    }