MST

星途 面试题库

面试题:Java多重通配符与类型擦除的关联

在Java中,已知泛型存在类型擦除机制。当使用多重通配符时,例如List<? extends Number>和List<? super Integer>,结合类型擦除原理,解释在运行时如何确保代码类型安全性,并举例说明可能出现的类型相关问题及解决方法。
24.3万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

类型擦除原理

在Java中,泛型主要是在编译期起作用,运行时会进行类型擦除。对于泛型类型参数,在编译后会被替换为其限定的上限(如果有),如果没有上限则替换为Object。例如List<Integer>在运行时实际类型是ListInteger类型信息被擦除。

确保代码类型安全性

  1. List<? extends Number>
    • 这种通配符表示该List可以包含Number及其子类的元素。由于类型擦除,运行时无法确切知道具体的元素类型,但编译器会在编译期进行类型检查。
    • 例如,以下代码在编译期会报错:
List<? extends Number> list1 = new ArrayList<>();
list1.add(new Integer(1)); // 编译错误,因为编译器不知道list1实际允许的具体类型
  • 但是可以安全地读取元素,因为返回类型至少是Number
List<? extends Number> list1 = new ArrayList<>();
Number num = list1.get(0);
  1. List<? super Integer>
    • 此通配符表示该List可以包含Integer及其超类的元素。同样由于类型擦除,运行时具体类型不确定,但编译期编译器会确保类型安全。
    • 可以向List中添加Integer及其子类元素:
List<? super Integer> list2 = new ArrayList<>();
list2.add(new Integer(1));
list2.add(new Double(2.0)); // 编译错误,因为Double不是Integer的子类
  • 读取元素时,由于不知道具体的上限类型,只能用Object接收:
List<? super Integer> list2 = new ArrayList<>();
Object obj = list2.get(0);

可能出现的类型相关问题及解决方法

  1. 问题
    • 类型不匹配问题。例如,尝试将错误类型的元素添加到List中,如上面List<? extends Number>中添加Integer元素的情况。
  2. 解决方法
    • 避免直接向List<? extends Number>中添加元素,如果需要添加元素,可以定义一个方法来处理,方法参数为具体的类型。例如:
List<Number> numbers = new ArrayList<>();
void addNumber(List<? super Number> list, Number num) {
    list.add(num);
}
addNumber(numbers, new Integer(1));
  • 对于读取List<? super Integer>的情况,如果需要特定类型的元素,可以在获取元素后进行类型检查和转换:
List<? super Integer> list2 = new ArrayList<>();
list2.add(new Integer(1));
Object obj = list2.get(0);
if (obj instanceof Integer) {
    Integer intValue = (Integer) obj;
    // 处理Integer值
}