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

为何Kotlin中可将子类类型List赋值给父类类型List?

为什么Java和Kotlin中泛型集合的赋值行为不一样?

1. Java的List<T>是「不变类型」

Java里的List<T>属于**不变(invariant)**泛型,简单说就是:哪怕FavouriteNote继承自Note,List<FavouriteNote>和List<Note>也完全是两个无关的类型,不能互相赋值。

  • 背后原因是Java的List是可读写的:如果允许把List<FavouriteNote>赋值给List<Note>,后续你可能会往notes里加一个普通Note对象,这就会导致原本只能存FavouriteNote的集合混入父类实例,运行时必然报错。编译器直接把这种风险掐死在编译阶段,所以你写的代码编译不通过。

2. Kotlin的List<T>是「协变类型」

Kotlin的List<T>接口天生是**协变(covariant)**的,它的定义是interface List<out E> : Collection<E>,这里的out关键字就是协变的标记。

  • 协变的意思是:如果FavouriteNote是Note的子类,那么List<FavouriteNote>自动成为List<Note>的子类,可以直接向上赋值。
  • 为什么安全?因为Kotlin的List是只读集合,它没有任何添加、修改元素的方法(这些操作全在MutableList里)。既然不能往里面加东西,就不存在混入非法类型的风险,完全保证类型安全。你示例里用的emptyList()返回的就是这种只读的协变集合,所以赋值能成功编译运行。

可以参考的学习内容

  • Kotlin官方文档里的泛型章节,重点啃out/in修饰符的作用,以及只读集合和可变集合的设计区别。
  • Java官方文档中关于泛型不变性的说明,顺便理解? extends T通配符的用法——这是Java里模拟只读协变的方式,比如List<? extends Note>就能接收List<FavouriteNote>。
  • 对比两种语言泛型的设计思路,核心看它们是怎么在类型安全和易用性之间做平衡的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 03:25:35