1

why below code can run?

fun main(args: Array<String>) {


    val somePair: Pair<Any?, Any?> = "items" to listOf("1","2a")
    var W=somePair.second as List<Int>
    println(W)
}

output:[1, 2a]

"2a" is not Int , but the type of W is List, why no exception throw?

koner
  • 45
  • 6
  • Does this answer your question? [Java generics type erasure: when and what happens?](https://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens) – Lino Jan 28 '22 at 08:26
  • Also related: [How does erasure work in Kotlin?](https://stackoverflow.com/q/42916801/5515060) – Lino Jan 28 '22 at 08:27
  • 1
    Also note that you get a warning from the compiler that the cast (`as List`) is unchecked. – broot Jan 28 '22 at 08:31
  • Casting is legal because you are casting `Any?` to `List`, so no exception here is expected, compiler will not analyze the actual content of list. `println(W)` implicitly invokes `W.toString()` (which is actually `List.toString()`, type Int is erased here) so no exception is expected either. Exception will be thrown if you print 2nd element of list (`println(W[1])`) because "2a" can't be cast to Int – Nikolai Shevchenko Jan 28 '22 at 08:39

1 Answers1

2

Compiling your code gives the following warning:

Unchecked cast: Any? to List<Int>

This literally means that the cast will not throw an exception in all cases. If you choose to ignore this warning, you should be prepared for this behaviour to happen.

Now as to why this actually runs fine, keep in mind that generic types are erased at runtime. This means that a List<String> or a List<Int> is actually just a raw List at runtime, the information about the element type is lost.

The point of the generics is mostly to help when compiling the code: the compiler prevents you from adding elements of the wrong type to the list, and it helps you when you read elements from the list by giving you a value with the proper type (no cast required).

Casts, however, operate at runtime. They check the runtime type of an object against a given type. The type List<Int> that you cast to is a generic type, and the compiler warns you because at runtime it will only see the raw interface List.

More concretely, somePair.second as List<Int> compares the runtime type of somePair.second (which is ArrayList here) with the raw List interface - and that is a match, so no exception.

Joffrey
  • 32,348
  • 6
  • 68
  • 100