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

Kotlin中逆变类型能否读取?无界通配符为何可读取?

问题解答

1. 逆变类型是否完全无法读取?

不是完全读不了,但不能直接通过逆变投影的集合调用读取方法:

  • 像List<in Class1>这种逆变投影,设计初衷是用来往里塞东西的(消费者):它能安全调用的是那些需要传入泛型类型参数的方法,比如add(),因为逆变保证它能接受Class1及其子类的对象。
  • 但它不能直接调用get()这种往外拿东西的方法(生产者)——编译器没法确定拿出来的到底是什么类型。比如你例子里的list实际是List<Class2>,但逆变投影只知道它能装Class1,拿出来的可能是Class2甚至更上层的类型,没法和Class1体系安全关联,所以直接调用get()会报错。
  • 如果非要读,可以先把逆变投影转成List<*>再读,比如:
fun main() {
    val list2: List<Class2> = listOf(Class2(), Class2())
    val list: List<in Class1> = list2 
    val item: Any? = (list as List<*>)[0]
}

2. 为何无界通配符*允许读取?它不该同时具备协变与逆变的限制吗?

这是对*的误解:

  • Kotlin里的List<*>其实是List<out Any?>的简化写法,属于协变投影,不是同时卡协变和逆变的限制。
  • 协变投影的定位是用来往外拿东西的(生产者):所以它能安全调用get()这类读取方法,返回值会被自动转成Any?——任何类型都能转成Any?,完全安全。
  • 它的限制是不能随便往里塞东西(除了null),因为编译器不知道这个集合的真实泛型类型,乱塞元素会破坏类型安全。
  • 简单说,List<*>是“能读不能写(除了null)”,和你以为的“既不能读也不能写”完全不是一回事。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 04:12:06