MST
星途 面试题库

面试题:Java泛型通配符与继承关系在复杂场景下的应用

给定一个方法`void processList(List<? extends Number> list)`,现在有两个类`IntegerSub extends Integer`和`DoubleSub extends Double`。创建`List<IntegerSub>`和`List<DoubleSub>`,能否将这两个列表作为参数传入上述方法?如果可以,在方法内部对列表元素进行操作时需要注意什么?如果不可以,如何修改方法签名以使其能接受这两种类型的列表,同时要保证类型安全。请详细阐述你的思路和解决方案。
44.2万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. 能否直接传入
    • 可以将List<IntegerSub>List<DoubleSub>作为参数传入void processList(List<? extends Number> list)方法。因为IntegerSubInteger的子类,IntegerNumber的子类,DoubleSubDouble的子类,DoubleNumber的子类,满足? extends Number的类型限定。
  2. 方法内部操作注意事项
    • 由于使用了通配符? extends Number,在方法内部不能向列表中添加元素(除了null)。因为编译器无法确定具体的类型,添加非null元素可能会导致类型不匹配错误。例如:
    void processList(List<? extends Number> list) {
        // list.add(new Integer(1)); // 编译错误
        list.add(null); // 可以
    }
    
    • 但是可以从列表中读取元素,并且返回的元素类型是Number。例如:
    void processList(List<? extends Number> list) {
        for (Number num : list) {
            double result = num.doubleValue();
            System.out.println(result);
        }
    }
    
  3. 修改方法签名以支持添加元素并保证类型安全
    • 可以使用类型参数来代替通配符。例如:
    <T extends Number> void processList(List<T> list) {
        // 现在可以添加T类型的元素
        list.add((T) new Integer(1)); // 这里假设T是Integer的子类,实际使用时要根据具体逻辑
        for (T num : list) {
            double result = num.doubleValue();
            System.out.println(result);
        }
    }
    
    • 这样修改后,在调用该方法时,编译器可以根据传入列表的具体类型来确定T的类型,从而保证类型安全,并且可以向列表中添加元素。例如:
    List<IntegerSub> intSubList = new ArrayList<>();
    processList(intSubList);