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

Kotlin泛型:为何List<Int>、LinkedList<Int>无法add null但Queue<Int>可以?

Kotlin中Queue<Int>可添加null但LinkedList<Int>/MutableList<Int>编译报错的原因

问题现象

对应测试代码如下:

import java.util.LinkedList
import java.util.Queue

fun main() {
    val list = mutableListOf<Int>()
    list.add(null) // 编译不通过,符合非空泛型的预期

    val linkedList: LinkedList<Int> = LinkedList()
    linkedList.add(null) // 编译不通过

    val queue: Queue<Int> = LinkedList()
    queue.add(null) // 无编译报错,运行可正常执行
}

根本原因

这个差异和泛型的协变、逆变规则没有关系,完全是Kotlin和Java互操作时的平台类型处理逻辑导致的:

  • kotlin.collections.MutableList是Kotlin原生定义的集合接口,它的add方法明确要求参数为非空的泛型类型E。当你声明泛型为非空的Int时,add方法只接受非空Int值,传null会直接被编译期空安全检查拦截。
  • java.util.LinkedList是Java标准库提供的类,当你直接用LinkedList<Int>作为变量类型声明时,Kotlin会将你指定的非空泛型Int的约束应用到类的所有方法上,此时add方法的参数被识别为非空Int,传null同样会被编译拦截。
  • 当你把LinkedList实例向上赋值给Queue<Int>类型的变量时,Kotlin读取的是Java原生java.util.Queue接口的方法签名。Java的Queue接口没有给泛型参数加任何@NonNull/@Nullable注解,Kotlin会将这里add方法的参数识别为平台类型Int!。平台类型不做编译期的空安全校验,你可以传非空值,也可以传null,编译器不会报错。

注意事项

  • Java原生LinkedList本身就支持存储null元素,因此queue.add(null)不仅编译能过,运行时也不会抛异常,null会被正常加入队列。
  • 不要依赖这种隐式的编译检查来保证集合内无null:如果要求队列元素非空,要么使用Kotlin原生提供的非空集合实现,要么在添加元素时手动做null校验,避免Java互操作带来的空指针隐患。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 05:03:39