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

Java集合协变在包装类中的运行机制及Holder赋值编译问题

问题原因与解决方案

核心原因

Java泛型类默认是不变的——哪怕类型A是类型B的子类型,Holder<A>和Holder<B>之间也不存在继承关系。而你能成功赋值List变量,是因为通配符? extends带来的协变特性,但这个特性不会自动传递给包装它的Holder类。

为什么List的赋值能通过?

List<? extends Base>是一个协变通配符类型,它表示「任意Base子类型的List」:

  • List<? extends Sub0>本质是「任意Sub0子类型的List」,而Sub0是Base的子类,所以它是List<? extends Base>的子类型,因此x = test0合法;
  • List<Sub1>是「具体Sub1类型的List」,Sub1也是Base的子类,自然也属于List<? extends Base>的范畴,所以x = test1也合法。

为什么Holder的赋值失败?

你的Holder<List<? extends Base>> z是一个具体泛型类型,而Holder<List<? extends Sub0>>和Holder<List<Sub1>>是另外两个独立的具体泛型类型——它们之间没有任何继承关系,就像你不能把Holder<String>赋值给Holder<Object>一样,编译器会直接报错。

解决方法

给Holder的泛型参数也加上通配符,让它支持协变:

// 修改z的类型为带通配符的Holder
Holder<? extends List<? extends Base>> z = ha;
z = hb;

这样z的类型表示「任意继承自List<? extends Base>的类型的Holder」,Holder<List<? extends Sub0>>和Holder<List<Sub1>>都符合这个条件,就能正常赋值了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:37:09