说到 map ,我对Kotlin 的零安全特性感到困惑.我有一个Map<String, String>.然而,我可以调用map.get(null),它返回null,表示该键不在 map 中.我预计会出现编译器错误,因为mapMap<String, String>而不是Map<String?, String>.我怎么能在String次辩论中通过null次呢?

还有一个相关的问题:如果我调用get(null),是否有任何类型的映射,无论是stdlib-one还是第三方实现,都可能抛出NullPointerException?我想知道对于Map的任何有效实现,调用map.get(s)而不是s?.let { map.get(it) }是否安全.

Update

编译器确实返回了一个带有map.get(null)的错误.但这是not,因为空安全性,但因为文字null没有向编译器提供所传递参数类型的指示.我的实际代码更像这样:

val map: Map<String, String> = ...
val s: String? = null
val t = map.get(s)

上面的编译很好,返回null.为什么密钥应该是不可为null的String

推荐答案

Map中的get方法声明如下:

abstract operator fun get(key: K): V?

因此,对于Map<String, String>,其get方法应该只需要Strings.

然而,还有另一个get扩展功能,接收器类型为Map<out K, V>:

operator fun <K, V> Map<out K, V>.get(key: K): V?

协方差out K是造成所有差异的原因.Map<String, String>Map<out String?, String>的一种,因为StringString?的一个子类型.就这get而言,以狗为键的 map 是以动物为键的 map .

val notNullableMap = mapOf("1" to "2")
// this compiles, showing that Map<String, String> is a kind of Map<out String?, String>
val nullableMap: Map<out String?, String> = notNullableMap

这就是为什么你可以把String?传给map.get,其中mapMap<String, String>.由于协方差out Kmap被视为"一种"Map<String?, String>.

还有一个相关的问题:如果我调用get(null),是否有任何类型的映射(无论是stdlib-one还是第三方实现)可能抛出NullPointerException?

请注意,这get是一个扩展函数,可用于实现Map的每种类型,因此不,没有任何类型的Map不具有这种行为.可能有一种类型实现了一个映射,但没有实现Map,但这将是非常非传统的,我不知道有人做这样的事情.

Kotlin相关问答推荐

在Kotlin中可以连接两个范围吗?

用普通Kotlin理解Gradle的Kotlin DSL'""

如何修改muableStateMapOf的值?

如何使用 Mockk 模拟返回值类的 Kotlin 函数类型?

如果带注释的成员未被特定块包围,则发出 IDE 警告

PRDownloader 即使在实现库后也无法工作.未知参考:Android Studio 中的 PRDownloader

Kotlin 具体类从抽象类和接口扩展而来,接口使用抽象类中实现的方法

Kotlin:查找集合中最常见的元素

判断 AAR 元数据值时发现的一个或多个问题:

Kotlin 和 Java 字符串拆分与正则表达式的区别

如何用 kotlin 打包 List

kotlin-bom 库是做什么的?

Kotlin:使用Gradle进行增量编译

如何将 Kotlin 日期中的字符串或时间戳格式化为指定的首选格式?

使用Dagger 2提供函数依赖性

Kotlin:如何从另一个类访问字段?

修改扩展函数中的this

在Kotlin中将列表转换为对的惯用方法

递归方法调用在 kotlin 中导致 StackOverFlowError 但在 java 中没有

Java的Kotlin:字段是否可以为空?