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

泛型不变性、协变与逆变问题:Kotlin示例代码不符合规则原因求解

核心误区说明

你对泛型变型规则的理解存在一个常见混淆:变型规则约束的是「泛型类本身的子类型关系」,和「泛型类构造参数的子类型多态」是完全独立的两套规则,你看到的「不符合预期」的表现,本质是普通的子类向上转型特性,和泛型变型没有关系。


问题1:为什么val invariantC: Invariant<B> = Invariant(C())可以编译通过?

不变泛型的规则是:Invariant<T>和Invariant<其他任何非T类型>都不存在子类型关系,这条规则本身没有问题。
你这段代码能编译通过的原因是Kotlin的构造器类型推断:
你没有显式指定Invariant(C())的泛型参数,Kotlin会根据左侧变量的声明类型Invariant<B>,自动推断构造器的泛型参数为B,而C是B的子类,子类实例当然可以向上转型传给需要B类型的构造参数,完全符合普通的面向对象规则。

如果显式指定泛型参数为C,就能触发你预期的不变规则报错:

// 显式指定泛型为C,此时Invariant<C>和Invariant<B>无父子关系,编译报错
val invariantC: Invariant<B> = Invariant<C>(C())

问题2:为什么val contravariantC: Contravariant<B> = Contravariant(C())可以编译通过?

逆变泛型的规则是:如果C是B的子类,那么Contravariant<B>是Contravariant<C>的子类型,反过来不成立,这条规则也没有问题。
同样是构造器类型推断的原因:Kotlin根据左侧变量类型Contravariant<B>,推断构造器的泛型参数为B,C作为B的子类当然可以传入构造参数,和逆变规则无关。

如果显式指定泛型参数为C,就能触发你预期的逆变规则报错:

// 显式指定泛型为C,此时Contravariant<C>不是Contravariant<B>的子类型,编译报错
val contravariantC: Contravariant<B> = Contravariant<C>(C())

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 05:45:00