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

为何可在协变类型List中传入逆变参数?Kotlin泛型疑问

为什么逆变类型参数I能传入协变的List中?

先明确两个核心类型概念:

  • 协变(out):比如List<out E>,若A是B的子类,List<A>可直接当作List<B>使用——相当于对外输出的类型可以更具体。
  • 逆变(in):比如ListMapper<in I>,若A是B的子类,ListMapper<B, O>可直接当作ListMapper<A, O>使用——相当于对内接收的类型可以更宽泛。

结合你的代码来拆解:

1. List的协变特性

List<out E>的协变意味着:如果I1是I2的子类,那么List<I1>是List<I2>的子类型。比如Dog继承自Animal,List<Dog>可以赋值给List<Animal>。

2. ListMapper中I的逆变要求

ListMapper<in I, out O>的逆变要求:如果I1是I2的子类,ListMapper<I2, O>必须能适配成ListMapper<I1, O>。

3. 两者的兼容性匹配

你的ListMapper继承自Mapper<List<I>, List<O>>,这里隐含了Mapper的第一个类型参数(输入类型)是逆变的(类似Kotlin标准库Function1<in P, out R>的输入参数P)。

当I是逆变类型时,List<I>作为Mapper的输入类型,刚好满足兼容性:

  • 假设I2是I1的父类,ListMapper<I2, O>对应Mapper<List<I2>, List<O>>
  • 因为List是协变的,List<I1>是List<I2>的子类型
  • 而Mapper的输入参数是逆变的,所以Mapper<List<I2>, List<O>>可以适配成Mapper<List<I1>, List<O>>,也就是ListMapper<I2, O>可以适配成ListMapper<I1, O>——完全符合I的逆变要求。

简单说,I的逆变和List的协变在这里是互补的,刚好满足整个类型体系的兼容性规则,所以这种写法是合法的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 04:50:28