【问题标题】:Why does HashMap.get not return a nullable type?为什么 HashMap.get 不返回可为空的类型?
【发布时间】:2015-06-26 05:58:27
【问题描述】:

我有点惊讶下面的例子抛出了NullPointerException

fun main(args: Array<String>) {
    val hm = HashMap<String, Int>()
    hm.put("alice", 42)
    val x = hm.get("bob")
    println(x)   // BOOM
}

我以为 Kotlin 代码中没有 NullPointerExceptions?

如果我用可选类型注释x,程序将打印null

fun main(args: Array<String>) {
    val hm = HashMap<String, Int>()
    hm.put("alice", 42)
    val x: Int? = hm.get("bob")
    println(x)   // null
}

我是否发现了一个特殊情况,或者这是 Kotlin/Java 互操作的普遍问题?

我正在使用带有 Kotlin 0.11.91.1 插件的 IntelliJ IDEA 14.1 社区版。

【问题讨论】:

标签: nullpointerexception null kotlin java-collections-api java-interop


【解决方案1】:

您的变量hmHashMap 类型,因为这是一个平台类,它的方法返回platform types。 Kotlin 自己的 Map 及其 subtrait 子接口 MutableMap 但是为 get() 返回可为空的类型。

将您的代码更改为

val hm : MutableMap<String, Int> = HashMap()

它会打印“null”。

【讨论】:

  • 为什么将trait 替换为interface?文档说trait
  • blog.jetbrains.com/kotlin/2015/04/… 说“trait”将被弃用,取而代之的是“interface”。
  • 此代码示例应为:val hm = hashMapOf&lt;String, Int&gt;() 或将示例中的地图直接创建为只读val hm = mapOf("alice" to 42)
  • @jayson val hm = hashMapOf&lt;String, Int&gt;() 将再次创建一个HashMap 类型的变量,而不是MutableMap 这才是重点。
  • 我想我应该更清楚地说明该评论。这不是目前和 Kotlin 的问题,当时是一个错误,现在你可以做他最初做的事情或我给出的两个例子。在另一个答案中查看完整的注释。
【解决方案2】:

这不再是问题。 Kotlin 对 JDK 类如何注释告诉它如何处理某些方法存在问题。当前的 Kotlin 没有出现您看到的问题。

这两个都从 Java 集合中返回一个 HashMap,第一个 hm1 更惯用。

val hm1 = hashMapOf<String, Int>()
val hm2 = HashMap<String, Int>()

如果提前知道值,您也可以将其创建为已经包含值的地图。

val hm3 = hashMapOf("alice" to 42)

或只读版本:

val hm4 = mapOf("alice" to 42)

在所有这些版本中,当使用未知值调用 get() 然后打印结果时,它们都会打印 null

println(hm1.get("missing"))
println(hm2.get("missing"))
println(hm3.get("missing"))
println(hm4.get("missing"))

所有get() 都具有相同的签名,因为 JDK 类由 Kotlin 团队注释以知道 get() 返回一个可为空的值,在这种情况下为 Int?

只有这些注释中的错误才会导致问题。如果您在 JDK 运行时库中看到另一个,则应该是 tracked as a bug

【讨论】:

    猜你喜欢
    • 2022-12-03
    • 1970-01-01
    • 2020-09-16
    • 2021-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多