fredoverflow
fredoverflow

Reputation: 263118

Why does HashMap.get not return a nullable type?

I was a bit surprised that the following example throws a NullPointerException:

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

I thought there are no NullPointerExceptions in Kotlin code?

If I annotate x with an optional type, the programm prints null instead:

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

Have I discovered a special case, or is this a general problem with Kotlin/Java interop?

I am using IntelliJ IDEA 14.1 Community Edition with Kotlin 0.11.91.1 plugin.

Upvotes: 3

Views: 2795

Answers (2)

Jayson Minard
Jayson Minard

Reputation: 85946

This is no longer an issue. Kotlin had an issue with how the JDK class was annotated telling it how to treat some methods. Current Kotlin does not exhibit the problem you were seeing.

These both return a HashMap from Java collections, the first hm1 being more idiomatic.

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

You can also create it as a map that already has the values if they are known ahead of time.

val hm3 = hashMapOf("alice" to 42)

or a readonly version:

val hm4 = mapOf("alice" to 42)

In all of these versions, they all print null when calling get() with an unknown value and then printing the result:

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

All have the same signature for get() since the JDK classes are annotated by the Kotlin team to know that get() returns a nullable value, Int? in this case.

Only an error in those annotations would cause a problem. And should be tracked as a bug if you see another one within the JDK runtime library.

Upvotes: 0

Kirill Rakhman
Kirill Rakhman

Reputation: 43811

Your variable hm is of type HashMap and because that's a platform class its methods return platform types. Kotlin's own Map and its subtrait subinterface MutableMap however return nullable types for get().

Change your code to

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

and it will print "null".

Upvotes: 6

Related Questions