Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are Kotlin's reified types incorrect for primitives on the JVM?

If a Kotlin function invocation reifies a primitive, say Int, the 'passed' class is that for the boxed primitive, not the unboxed version.

inline fun <reified T> reify() = T::class

@Test fun reified_type_doesnt_match_for_primitive() {
    assertNotEquals(Int::class, reify<Int>())
    assertNotEquals(Int::class.java, reify<Int>().java)
    assertNotEquals<Any>(Int::class, reify<Int?>())

    val nullableInt: Int? = 42
    assertNotEquals(nullableInt!!.javaClass.kotlin, reify<Int>())

    assertEquals<Any>(java.lang.Integer::class.java, reify<Int>().java)
}

@Test fun reified_type_matches_for_class() {
    assertEquals(String::class, reify<String>())
}

Is this a bug?

like image 823
Duncan McGregor Avatar asked Nov 29 '15 20:11

Duncan McGregor


People also ask

Does Kotlin support primitive data types in similar way as java?

Kotlin doesn't have primitive type (I mean you cannot declare primitive directly). It uses classes like Int , Float as an object wrapper for primitives. When kotlin code is converted to jvm code, whenever possible, "primitive object" is converted to java primitive.

What is reified function?

"reified" is a special type of keyword that helps Kotlin developers to access the information related to a class at runtime. "reified" can only be used with inline functions. When "reified" keyword is used, the compiler copies the function's bytecode to every section of the code where the function has been called.

Is string a primitive data type in Kotlin?

The most fundamental data type in Kotlin is the Primitive data type and all others are reference types like array and string.


1 Answers

This is somewhat confusing, but the current behavior is by design. This approach has a major benefit compared to the one where we would treat T::class.java as a primitive class. If the function has a parameter of type T, its Java class is always equal to T::class.java at runtime (assuming T is final). This is actually a very sensible thing to expect:

    inline fun <reified T : Any> foo(t: T) {
        assert(T::class.java == t.javaClass)
    }

This happens because the parameter of a generic type T can only have a reference value at runtime, which is necessarily a boxed value if T is a primitive type.

Also see a thread on the Kotlin forum on this subject: https://devnet.jetbrains.com/thread/475540

like image 129
Alexander Udalov Avatar answered Sep 21 '22 02:09

Alexander Udalov