k31*_*159 2 kotlin kotlin-null-safety
当涉及到地图时,我对 Kotlin 的 null 安全功能感到困惑。我有一个Map<String, String>。但我可以打电话map.get(null),它会返回null以指示地图中不存在该钥匙。我预计会出现编译器错误,因为map是 aMap<String, String>而不是Map<String?, String>. 我怎么可以通过null争论String呢?
还有一个相关的问题:是否有任何类型的 Map,无论是 stdlib 还是第三方实现,NullPointerException如果我调用,可能会抛出异常get(null)?我想知道对于 的任何有效实现,调用map.get(s)而不是,是否安全。s?.let { map.get(it) }Map
更新
编译器确实返回了一个错误map.get(null)。但这并不是因为空安全,而是因为文字null没有向编译器指示所传递参数的类型。我的实际代码更像是这样的:
val map: Map<String, String> = ...
val s: String? = null
val t = map.get(s)
Run Code Online (Sandbox Code Playgroud)
上面的代码编译良好,并返回null. 当键应该是String不可空的时,为什么会这样呢?
get中的方法声明Map如下:
abstract operator fun get(key: K): V?
Run Code Online (Sandbox Code Playgroud)
所以对于 a Map<String, String>,它的get方法应该只接受Strings 。
然而,还有另一个get扩展函数,其接收者类型为Map<out K, V>:
operator fun <K, V> Map<out K, V>.get(key: K): V?
Run Code Online (Sandbox Code Playgroud)
协变out K是造成所有差异的原因。Map<String, String>是一种Map<out String?, String>,因为String是 的子类型String?。就这一点而言get,以狗为键的地图“是”以动物为键的地图。
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
Run Code Online (Sandbox Code Playgroud)
这就是为什么你可以将 a 传入其中String?,map.get其中mapa Map<String, String>。由于协变,它们map被视为“一种” 。Map<String?, String>out K
还有一个相关的问题:是否有任何类型的 Map(无论是 stdlib 实现还是第三方实现)如果我调用 get(null) 可能会抛出 NullPointerException?
是的,在 JVM 上TreeMap(使用不处理空值的比较器)不支持空键。比较:
val map = TreeMap<Int, Int>()
println(map[null as Int?]) // exception!
Run Code Online (Sandbox Code Playgroud)
和:
val map = TreeMap<Int, Int>(Comparator.nullsLast(Comparator.naturalOrder()))
println(map[null as Int?]) // null
Run Code Online (Sandbox Code Playgroud)
但是,请注意,由于问题get是每个都可用的扩展函数Map,因此只要您的映射实现了Map.
| 归档时间: |
|
| 查看次数: |
2457 次 |
| 最近记录: |