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

Java嵌套泛型(super与extends混合)赋值问题及有效构造咨询

Java泛型赋值兼容问题解析

先明确几个核心规则:Java泛型默认是不变的(即不带通配符时,泛型类型必须严格匹配);? extends T是协变(允许子类型泛型赋值给父类型泛型容器);? super T是逆变(允许父类型泛型赋值给子类型泛型容器)。

为什么l1的赋值有效?

看这段代码:

List<? extends ArrayList<? extends Integer>> l1 = new ArrayList<ArrayList<Integer>>();

左侧的泛型是? extends ArrayList<? extends Integer>,表示这个List的元素可以是ArrayList<? extends Integer>或者它的任何子类型。右侧的ArrayList<Integer>是ArrayList<? extends Integer>的子类型(因为Integer是? extends Integer的具体实现),所以ArrayList<ArrayList<Integer>>完全符合左侧? extends ArrayList<? extends Integer>的协变要求,再加上ArrayList是List的实现类,因此这个赋值完全合法。

为什么l2和l3会报错?

关于l2的错误

代码:

List<ArrayList<? extends Integer>> l2 = new ArrayList<ArrayList<Integer>>();

左侧是无通配符的严格泛型,要求右侧的泛型参数必须和左侧完全一致。这里左侧的泛型参数是ArrayList<? extends Integer>,而右侧是ArrayList<Integer>——前者是后者的父类型,但泛型在无通配符时是不变的,不能把子类型泛型的容器赋值给父类型泛型的容器,因此编译器判定为不兼容类型。

关于l3的错误

代码:

List<? super ArrayList<? extends Integer>> l3 = new ArrayList<ArrayList<Integer>>();

左侧的? super ArrayList<? extends Integer>是逆变通配符,要求右侧的泛型参数必须是ArrayList<? extends Integer>的父类型。但右侧的ArrayList<Integer>是ArrayList<? extends Integer>的子类型,不符合逆变的要求,所以报错。

l2和l3的有效构造方式

构造合法的l2

只需要让右侧的泛型参数和左侧完全一致即可,示例:

// 显式指定泛型参数
List<ArrayList<? extends Integer>> l2 = new ArrayList<ArrayList<? extends Integer>>();
// Java 7+ 可用菱形语法自动推断
List<ArrayList<? extends Integer>> l2 = new ArrayList<>();
// 也可以直接初始化包含符合要求的元素
List<ArrayList<? extends Integer>> l2 = new ArrayList<>(List.of(new ArrayList<Integer>()));

构造合法的l3

需要让右侧的泛型参数是ArrayList<? extends Integer>的父类型,比如List<? extends Integer>、Collection<? extends Integer>甚至Object,示例:

// 用List<? extends Integer>作为泛型参数(ArrayList是List的子类)
List<? super ArrayList<? extends Integer>> l3 = new ArrayList<List<? extends Integer>>();
// 用更上层的Collection<? extends Integer>
List<? super ArrayList<? extends Integer>> l3 = new ArrayList<Collection<? extends Integer>>();
// 最宽泛的用Object
List<? super ArrayList<? extends Integer>> l3 = new ArrayList<Object>();
// 菱形语法会自动推断为ArrayList<Object>,也合法
List<? super ArrayList<? extends Integer>> l3 = new ArrayList<>();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 17:27:15