Следующий фрагмент показывает результат проверки равенства ссылок 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
.
Документы говорят:
Возвращает экземпляр класса Java, соответствующий данному экземпляру KClass. В случае примитивных типов он возвращает соответствующие классы-оболочки.
Т.е. c.javaObjectType == c1.javaObjectType
имеет значение true
Но это не оправдывает, почему KClass
es, имеющие одинаковое строковое представление, различны. По крайней мере, это сбивает с толку. И это хорошая идея отметить об этом в документах.
В вашем случае равенство не выполняется, потому что KClass
es считаются равными, когда они соответствуют одному и тому же типу 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
Я согласен с тем, что эта семантика довольно запутанная, я задал вопрос об этом.
Кроме того, KClass
не отражает нулеустойчивость типов Kotlin, и в случае, если вам нужно точно работать с объявленными типами Kotlin, вам нужно будет использовать KType
, что и делает.
UPD: проблема отмечена как фиксированная, и равенство объясняется в KClass.equals
KDoc с 1.0.2.