Kotlin 的具体化类型对于 JVM 上的原语是否不正确?
Are Kotlin's reified types incorrect for primitives on the JVM?
如果 Kotlin 函数调用具体化了一个原语,比如 Int
,'passed' class 是针对装箱原语的,而不是未装箱版本。
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
视为原始 class 的方法相比,这种方法有一个主要好处。如果函数有一个 T
类型的参数,它的 Java class 在运行时总是等于 T::class.java
(假设 T
是最终的)。这其实是一件非常明智的事情:
inline fun <reified T : Any> foo(t: T) {
assert(T::class.java == t.javaClass)
}
出现这种情况是因为泛型的参数T
在运行时只能有一个引用值,如果T
是一个基本类型,它必然是一个装箱值。
另请参阅 Kotlin 论坛上关于此主题的帖子:https://devnet.jetbrains.com/thread/475540
如果 Kotlin 函数调用具体化了一个原语,比如 Int
,'passed' class 是针对装箱原语的,而不是未装箱版本。
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
视为原始 class 的方法相比,这种方法有一个主要好处。如果函数有一个 T
类型的参数,它的 Java class 在运行时总是等于 T::class.java
(假设 T
是最终的)。这其实是一件非常明智的事情:
inline fun <reified T : Any> foo(t: T) {
assert(T::class.java == t.javaClass)
}
出现这种情况是因为泛型的参数T
在运行时只能有一个引用值,如果T
是一个基本类型,它必然是一个装箱值。
另请参阅 Kotlin 论坛上关于此主题的帖子:https://devnet.jetbrains.com/thread/475540