Java基础教程(七十四)泛型之extends通配符:Java泛型边界突破,extends通配符如何向上突破枷锁?

一、痛点:泛型容器的类型僵化

Java泛型默认是不变(invariant) 的。这意味着List<Integer>并非List<Number>的子类型:

java

List<Integer> intList = new ArrayList<>();
List<Number> numList = intList; // 编译错误!类型不兼容

即使Integer是Number子类,其容器也无法直接赋值给父类容器引用,限制了代码复用。


二、协变救星:<? extends T>的核心机制

<? extends T>声明了泛型的上界(upper bound) ,允许接受T及其子类型:

java

List<? extends Number> numList = new ArrayList<Integer>(); // 合法!

此时numList成为“某种Number子类的列表”,实现了协变(covariance)


三、安全边界:生产者(Producer)的读写限制

✅ 允许读取(安全)

java

Number num = numList.get(0); // 安全:元素必为Number子类
Integer i = (Integer) numList.get(0); // 需显式向下转型(风险自控)
❌ 禁止写入(除null

java

numList.add(new Integer(10)); // 编译错误!
numList.add(new Double(1.0)); // 同样错误!
numList.add(null); // 唯一允许的写入操作

原因:编译器无法确定numList实际类型(可能是List<Double>),写入操作可能导致类型污染。


四、实战示例:灵活处理异构数值集合

java

// 计算任意Number子类列表的总和
public static double sumList(List<? extends Number> list) {
    double sum = 0.0;
    for (Number num : list) { // 安全读取
        sum += num.doubleValue();
    }
    return sum;
}

// 使用示例
List<Integer> integers = Arrays.asList(1, 2, 3);
List<Double> doubles = Arrays.asList(1.5, 2.5);
System.out.println(sumList(integers)); // 输出6.0
System.out.println(sumList(doubles)); // 输出4.0

此方法可处理IntegerDouble等所有Number子类的列表,无需重载。


五、设计哲学:PECS原则中的生产者(Producer)

PECS(Producer-Extends, Consumer-Super)原则中:

  • Producer:数据来源(如上述sumList参数),使用<? extends T>
  • Consumer:数据消费(如集合添加操作),需用<? super T>

六、Java API中的经典应用

java.util.Collectionscopy方法巧妙运用两者:

java

public static <T> void copy(
    List<? super T> dest, // 消费者:可写入T及其父类
    List<? extends T> src // 生产者:可读取T及其子类
) {
    for (int i = 0; i < src.size(); i++) {
        dest.set(i, src.get(i)); // 安全:src元素必是dest可接受的类型
    }
}

结语:解锁灵活性的双刃剑

extends通配符通过协变打破泛型容器继承链的隔阂,赋予API强大灵活性,代价是写入操作的严格限制。掌握其“生产者”定位与PECS原则,方能精准驾驭泛型系统,在安全与抽象之间找到最佳平衡点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

值引力

持续创作,多谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值