Kotlin中值为MutableList的MutableMap访问为何触发空安全报错
Kotlin MutableMap下标访问返回可空类型的原因
问题复现
在Kotlin环境运行如下代码时,编译器抛出Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type MutableList<String>?错误:
fun main() { val mlist: MutableList<String> = mutableListOf<String>() val mapp: MutableMap<Int, MutableList<String>> = mutableMapOf(1 to mlist) println(mapp) mapp[1].add("a") // 编译报错 println(mapp) }
明明已经显式声明Map的值类型为非空MutableList<String>,编译器仍判定下标访问的结果是可空类型,核心原因和Kotlin的Map接口设计逻辑直接相关。
核心判定逻辑
Map/MutableMap的下标访问(即get运算符重载)从接口定义层面就固定返回可空类型,和你声明的值类型是否非空没有关系。
查看MutableMap的get方法签名可以明确这点:
public operator fun get(key: K): V?
这个设计是完全符合逻辑的:get方法无法保证传入的key一定存在于Map中,当key不存在时方法会返回null——哪怕你声明的值类型V是不可空的,这个「key不存在返回null」的逻辑依然成立。
举个最直接的例子:如果代码写mapp[999].add("x"),Map中根本不存在key为999的条目,此时如果下标访问返回非空类型,就会直接触发空指针,完全破坏Kotlin的空安全设计。因此编译器只要看到是通过下标访问Map的值,就会将其识别为可空类型,强制开发者处理key不存在的场景。
容易遗漏的相关知识点
- 你声明的
MutableMap<Int, MutableList<String>>的非空约束,仅作用于Map实际存储的value:当你往Map中put值时,编译器会阻止你传入null,比如mapp[2] = null会直接编译报错,但这个约束不覆盖「key不存在返回null」的场景。 - 如果能100%确认key一定存在,可以用
getValue()方法替代下标访问,该方法返回非空类型V,找不到key时会抛出NoSuchElementException,写法为mapp.getValue(1).add("a"),不需要空安全调用。 - 空安全调用
mapp[1]?.add("a")的执行逻辑是:key存在时正常执行add操作,key不存在时直接跳过语句,不会抛出空指针。 - 如果需要实现「key不存在就自动创建对应value存入Map再返回」的逻辑,推荐用
getOrPut方法,写法更简洁:
// key=1存在就返回对应list,不存在就新建空list存入Map后返回 mapp.getOrPut(1) { mutableListOf() }.add("a")
内容的提问来源于stack exchange,提问作者LiTTle
相关产品推荐
相关产品推荐

