WMX · 随记
·Java· 3 分钟阅读

List<Integer> 为什么不是 List<Number>

Integer 是 Number 的子类,但把 List<Integer> 交给接受 List<Number> 的方法会编译失败。集合如果同时允许读写,简单的类型替换会破坏安全性。

Java 系列概览:类型与值、状态与资源、边界验证
Java 系列概览:类型与值、状态与资源、边界验证 点击图片查看大图 ↗

问题从哪里出现

Integer 是 Number 的子类,但把 List<Integer> 交给接受 List<Number> 的方法会编译失败。集合如果同时允许读写,简单的类型替换会破坏安全性。

理解核心机制

? extends Number 允许把元素当 Number 读取,却不能安全加入任意 Number;? super Integer 允许加入 Integer,但读取时只能保守视作 Object。根据方法是生产还是消费元素来设计边界。

动手做一个小实验

Java 17 或更新版本;将示例保存为 Demo.java,执行 javac Demo.java 后运行 java Demo。

Java11 行 · 可横向滚动
import java.util.List;
public class Demo {
    static double sum(List<? extends Number> values) {
        double result = 0;
        for (Number value : values) result += value.doubleValue();
        return result;
    }
    public static void main(String[] args) {
        System.out.println(sum(List.of(1, 2, 3)));
    }
}

适用边界与常见误区

通配符不是万能的灵活性开关,嵌套通配符可能让调用方难以理解。只读意图也不等于集合在运行时不可变。

继续练习

尝试在 sum 中添加一个 Double,阅读编译器错误;再设计一个仅向目标集合追加 Integer 的方法。

参考资料

阅读相关官方文档或原始资料 ↗

← 返回文章归档