以下代码段显示了测试从不同来源获得的Kotlin KClass
引用是否相等的结果。它们的字符串表示形式是相同的。但是它们的java类不同。期望c
,c0
和c1
相等。但是由于某些原因,它们不是。
有细微差别还是一个错误?如果不是错误,那么测试KClass
es是否相等的可靠方法是什么?
fun main(args: Array<String>) {
val c = Int::class
fun test(v0: Any, v1: Any) {
val c0 = v0.javaClass.kotlin
val c1 = v1.javaClass.kotlin
println("c= $c; c0= $c0; c1= $c1") // c= class kotlin.Int; c0= class kotlin.Int; c1= class kotlin.Int
println("c= ${c.java}; c0= ${c0.java}; c1= ${c1.java}") // c= int; c0= class java.lang.Integer; c1= class java.lang.Integer
println("c = c0? ${c == c0}; c0 = c1? ${c1 == c0}") // c = c0? false; c0 = c1? true
}
test(11, 22)
}
编辑:
解决方法是使用
KClass.javaObjectType
方法。该文档说:
IE。
c.javaObjectType == c1.javaObjectType
为true但这并不能说明为什么具有相同字符串表示形式的
KClass
是不同的。至少令人困惑。并且最好在文档中对此进行说明。 最佳答案
在您的情况下,相等性失败,因为KClass
对应于相同的Java类型而不是相同的Kotlin类型时,它们被视为相等。对于int
和java.lang.Integer
,这是错误的。
解决方法是使用KClass
的javaObjectType
属性,即使对于编译成Java原语的Kotlin类型,该属性也将返回Java类(不是原语类型):
fun sameClass(c1: KClass<*>, c2: KClass<*>) = c1.javaObjectType == c2.javaObjectType
sameClass(Int::class, (1 as Any?)!!.javaClass.kotlin) //true
我同意这种语义相当困惑,对此我filed an issue。
另外,
KClass
不能反射(reflect)Kotlin类型的可空性,并且如果您需要精确地使用声明的Kotlin类型,则需要使用KType
,它可以。UPD:,此问题已标记为已修复,并且自1.0.2起在
KClass.equals
KDoc中解释了该等同性。