Kotlin的指定类型是否对于JVM上的原语不正确?
如果一个Kotlin函数调用引用了一个原语,比如说Int
,那么这个“被传递”的类就是盒装原语的类,而不是未装箱的版本。
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>()) }
这是一个错误?
这有点令人困惑,但目前的行为是通过设计。 与我们将T::class.java
当作一个原始类的方法相比,这种方法有一个很大的好处。 如果函数具有类型T
的参数,则其Java类在运行时始终等于T::class.java
(假设T
是final)。 这实际上是一个非常明智的事情:
inline fun <reified T : Any> foo(t: T) { assert(T::class.java == t.javaClass) }
发生这种情况的原因是,泛型类型T
的参数在运行时只能有一个引用值,如果T
是基本类型,则必须是装箱值。
另请参阅Kotlin论坛上关于此主题的主题: https : //devnet.jetbrains.com/thread/475540