Kotlin:泛化的泛型似乎不适用于hash / equals比较
我有一个KClass
到Int
的地图。 然后我有一个具有泛化类型的函数。 然后,我会期待以下情况,因此,给我关联与Boolean::class
的Int
val kclassToInt = mapOf(Boolean::class to 1, Byte::class to 1, Short::class to 2) inline fun <reified T> myExpectations() = assertEquals(1, kclassToInt.getRaw(T::class), "Why doesn't it work? :'(")
我迎接了Why doesn't it work? :'(. Expected <1>, actual <null>.
Why doesn't it work? :'(. Expected <1>, actual <null>.
从调用它像这样myExpectations<Boolean>()
。
然后我试图使用.java
关闭,所以我使用Java的Class
而不是Kotlin的KClass
。
val classToInt = mapOf(Boolean::class.java to 1, Byte::class.java to 1, Short::class.java to 2) inline fun <reified T : Any> anotherExpectation() = assertEquals(1, classToInt.getRaw(T::class.java))
这一次,我再次迎来了断言错误: java.lang.AssertionError: Expected <1>, actual <null>.
最后,我尝试使用.javaClass
而不是.java
:
val javaClassToInt = mapOf(Boolean::class.javaClass to 1, Byte::class.javaClass to 1, Short::class.javaClass to 2) inline fun <reified T> pleaseWork() = assertEquals(1, javaClassToInt.getRaw(T::class.javaClass))
这一次真的很奇怪。 我被这个问候迎接: java.lang.AssertionError: Expected <1>, actual <2>.
这似乎是因为所有.javaClass
引用KClassImpl
。
最后我诉诸了我不想做的事,用.qualifiedName
:
val qnToInt = mapOf(Boolean::class.qualifiedName to 1, Byte::class.qualifiedName to 1, Short::class.qualifiedName to 2) inline fun <reified T> iKnowItWorks() = assertEquals(1, qnToInt.getRaw(T::class.qualifiedName))
哪一个当然有效,是我在我的实际使用情况下使用的: https : //github.com/Jire/kotmem/blob/master/src/main/kotlin/org/jire/kotmem/Process.kt
我相信Map中的关键类型是基本类型(Java int而不是Integer)的KClass
实例。 函数中的KClass
类型是盒装类型(Integer)的KClass
实例,如Kotlin的指定类型对于JVM上的原语不正确所示。
虽然这两个KClass
打印同样的东西,他们是不相同的,所以你的查找失败。
很可能你写了类似println(type.javaClass)
这似乎是有道理的,但实际上不是因为它总是打印class kotlin.reflect.jvm.internal.KClassImpl
,因为这是内部实现类的KClass
界面。
为什么type.javaClass
工作? javaClass
是一个扩展属性,它获得了作为接收者传递给它的任何值的运行时Java类。 其签名是:
val <T : Any> T.javaClass: Class<T>
type
是KClass<T>
type
的完全有效值,所以type.javaClass
的结果类型是Class<KClass<T>>
。 这已经几乎完全没有意义,除非你想要反思KClass
实现类的符号。 由于type
在运行时是KClassImpl
实例,因此type.javaClass
是一个Class
实例,代表名为kotlin.reflect.jvm.internal.KClassImpl
的类。
这有点混乱,绝对不是你想要做的。 如果你想打印一个类实例到屏幕上,你可以调用println(type)
。 如果您想获得与您所拥有的KClass
实例相对应的Java Class
实例,则可以使用java
扩展特性: type.java
。 java
的签名是:
val <T : Any> KClass<T>.java: Class<T>
所以如果type
是一个KClass<T>
,那么type.java
是一个Class<T>
。