You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何List<? extends Foo>无法添加Foo类对象?技术问询

为什么List<? extends Foo>不能添加Foo对象?

嘿,这个问题其实是Java泛型里一个非常典型的通配符误区,我来给你拆解明白~

首先得搞清楚List<? extends Foo>到底代表什么:它表示这个List是属于Foo的某个子类(包括Foo自己)的列表,但我们无法确定具体是哪一个子类。举个例子,这个list有可能是ArrayList<SubFoo1>,也有可能是ArrayList<SubFoo2>,甚至就是ArrayList<Foo>——但编译器不知道它到底是哪一种。

那为什么不能add Foo对象呢?咱们想个极端情况:假设你的list实际是ArrayList<SubFoo>(SubFoo是Foo的子类),如果编译器允许你往里面加一个父类Foo的对象,那这个List里就混进了非SubFoo类型的元素,后续从List里取元素的时候,你以为取出来的都是SubFoo,实际却是Foo,这就会引发类型转换异常,完全违背了泛型的类型安全设计。所以Java编译器干脆一刀切:只要是List<? extends T>,除了null之外,任何元素都不能add进去——因为它无法保证你加的元素和List实际的类型匹配。

那你想要的“可以存放Foo子类对象的List”该怎么写?其实很简单,直接用List<Foo>就足够了!List<Foo>本身就允许存放Foo以及它所有子类的对象,完全满足你的需求。

修改你的代码如下:

final Foo[] array = new Foo[] {new Foo()};
// 把<? extends Foo>改成Foo即可
final List<Foo> list = new ArrayList<>(array.length);
for (final Foo foo : array) {
    list.add(foo); // 现在可以正常编译啦
}

总结一下:

  • List<? extends T>是只读型的通配符,适合用来读取元素(比如遍历、获取元素),不适合写入;
  • 如果需要写入T或T的子类对象,直接用List<T>就好;
  • 要是需要定义能接受任意T子类List的参数,才用List<? extends T>,但此时同样不能往里面加元素(除了null)。

内容的提问来源于stack exchange,提问作者user7338524

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:02:57