whojes
whojes

Reputation: 23

Kotlin Map/List Nullable Type Safety

I'm new to kotlin, so i need some keywords for my questions.

here is my kotlin code:

fun foo(map: Map<String, Int>) {
  map.forEach {
    println(it.value.toString())
  }
}

This snippet can cause NPE when called like below:

fun main() {
  val map = mapOf("bar" to null) as Map<String, Int>
  foo(map)
}
  1. I don't know why this casting mapOf("bar" to null) as Map<String, Int> works without compile error.
  2. Don't know why function foo can cause NPE while it has no compile error or warnings or !!

I'm sure there is a similar question but i can't find questions or any key words.


well actually i use this map:

val objectMapper = jacksonObjectMapper()
val string = """ 
    { "value": null }
""".trimIndent()
// this is an example, origin string comes from RESTAPI input.
val convertedMap: Map<String, String> = objectMapper.readValue(string)

and it didn't make any warnings, and it caused NPE. I need some tips for using kotlin Map/List in order not to make unexpected errors.

Upvotes: 2

Views: 607

Answers (1)

Tenfour04
Tenfour04

Reputation: 93581

Casting is inherently unsafe. You are telling the compiler you know more about the object you are casting than the compiler does. There are a few cases where the compiler can give you an error when casting, when it can tell that you are casting something that could not possibly be a match for some other type.

When you cast to classes with no generics, you usually get no warning at all. It is assumed just like with !! that if you are casting, you know what you're doing. You have checked the possible logic and can confirm absolutely that the cast is safe, even though the compiler can't tell.

When you cast to a class with generics, the compiler will at least give you a warning about it. This is because the cast won't fail if the generic types are wrong. It will succeed because of type erasure, and then you'll get an error somewhere else in your code when you start interacting with the object. So the warning is there because it's even worse than a ClassCastException, because the resulting error happens somewhere else in your code than the line where you perform the cast, making it much harder to debug.

Suppressing a warning just makes the warning go away. It doesn't change behavior at all. Only suppress a warning when you've checked the possible failures it can cause and are sure that what you're doing is safe.

In the case of your Map, casting it to non-nullable values despite it containing null values will succeed at run time, but fail later when you retrieve the values.

Upvotes: 1

Related Questions