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

解惑Kotlin泛型中in/out关键字:为何对应Java的super/extends?

理解Kotlin泛型中in/out关键字的命名逻辑

Kotlin的out和in关键字是从数据流向和生产者/消费者角色出发设计的,比Java的? extends/? super更贴合实际使用场景,拆解来看逻辑非常清晰:

1. out Number:生产者(对应Java的? extends Number)

Array<out Number>能接收Array<Double>、Array<Short>这类Number子类的数组,核心原因是:

  • 这个数组是数据的生产者——你只能从里面读取数据(不能往里面写入非null值,否则会破坏类型安全),读取的元素都可以被安全当作Number类型使用。
  • 命名out的本质:数据是从这个容器**向外流出(out)**的,你只能拿取它产出的数据,无法向它输入数据。

比如你不能对Array<out Number>执行写入操作,如果实际传入的是Array<Double>,写入Int会直接导致类型错误;但你可以安全读取from[i]并赋值给Number类型变量。

2. in Number:消费者(对应Java的? super Number)

Array<in Number>能接收Array<Number>、Array<Object>这类Number超类的数组,核心原因是:

  • 这个数组是数据的消费者——你只能往里面写入Number或其子类的元素(读取的话只能拿到最顶层的超类类型,比如Any?),超类容器可以安全容纳所有子类实例。
  • 命名in的本质:数据是**向内流入(in)**这个容器的,你只能向它输入符合要求的数据,读取范围会被放大到超类。

比如你可以安全把Number类型元素写入Array<in Number>,不管它实际是Array<Number>还是Array<Object>;但读取时只能确定拿到的是Any?类型,因为超类容器可能存在其他类型元素。

对比Java的命名逻辑

Java用extends和super是从类型继承关系出发,而Kotlin的in/out是从数据使用方式出发:

  • Java的? extends Number强调「列表元素是Number的子类或本身」
  • Kotlin的out Number强调「这个容器只能产出Number类型的数据」
    两者本质等价,但Kotlin的命名更聚焦于你对容器的操作权限,而非单纯的类型继承关系。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 13:09:49