Strange `is` and `as` behavior


#1

I’m sure I’m missing something important here but what exactly is going on when I do this (aside from me experimenting with stupidity):

>>> val grades: List<Int> = listOf("A", "B", "C") as List<Int>
>>> grades.forEach { println("${it}") } // java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number

>>> grades[0] is Int // false
>>> grades[0] is String // error: incompatible types: String and Int

>>> grades[0] as Int // java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

Just started on Kotlin today and am super excited to understand the ins and outs, but I’m stuck on this :frowning: Thanks in advance!


#2

It works the way it does because generics are erased at runtime on the JVM, and it’s not possible to determine at runtime whether a List is a List<Int> or a List<String>; it’s only known that it’s a List. Chapter 9 of “Kotlin in Action” explains this specific example in much more detail.


#3

Just fiddled around kotlin jvm package. I think its because Kotlin does not know the type during runtime. Just execute the below code, you will find your answer. Is and As operate only on compile time hence you get exception immediately if it does not meet its rules.

/**
 * Created by abuabdul
 */
fun main(args: Array<String>) {
    val grades = listOf("A", "B", "C")
    println(grades.javaClass)

    val gradesString : List<String> = listOf("A", "B", "C")
    println(gradesString.javaClass)

    val gradesAsInt : List<Int> = listOf("A", "B", "C") as List<Int>
    println(gradesAsInt.javaClass)
}