проекция.

вая Котлин 1.1. Дляinstance какого-то класса,instance::class.java а такжеinstance.javaClass кажется почти эквивалентным:

val i = 0
println(i::class.java) // int
println(i.javaClass) // int
println(i::class.java === i.javaClass) // true

Однако есть небольшая разница:

val c1: Class<out Int> = i::class.java
val c2: Class<Int> = i.javaClass

instance.javaClass незначительно короче, ноinstance::class.java более соответствует соответствующему использованию типа. Пока вы можете использовать.javaClass на некоторых типах результат может не соответствовать ожидаемому:

println(i::class.java === Int::class.java) // true
println(i.javaClass === Int.javaClass) // false
println(Int::class.java === Int.javaClass) // false
println(Int.javaClass) // class kotlin.jvm.internal.IntCompanionObject

Итак, я бы сказал, что лучше никогда не использовать.javaClass для большей согласованности. Есть ли аргументы против этого?

 marstran10 окт. 2017 г., 22:09
Я думаю, что я где-то читал, чтоjavaClass считается устаревшим, но я не могу найти его прямо сейчас.

Ответы на вопрос(1)

foo статического (объявленного или предполагаемого) типаFoo:

foo.javaClass набирается какClass<Foo>

foo::class.java набирается какClass<out Foo>

На самом деле, последний является более точным, потому что фактическое значение, котороеfoo оценивает может быть примером неFoo сам по себе, но один из его подтипов (и это именно то, что обозначается ковариантнымout Foo).

Как правильно заметил @marstran в комментарии к вопросу,.javaClass однажды считался устаревшим (см.Объявление Kotlin 1.1 RC) потому что он может нарушить безопасность типов (см. ниже), но впоследствии он был оставлен как есть, потому что он широко использовался и заменял его альтернативой::class.java потребует добавления явных непроверенных приведений в коде.

Также смотрите комментарии под этим ответом:(ссылка)

Обратите внимание, чтоInt.javaClass не обозначает типInt но вместо этого класс JavaIntсопутствующий объект. В то время какInt::class.java является несвязанной ссылкой на класс и обозначает тип. Чтобы получить это с.javaClassнужно позвонить наInt например, например1.javaClass.

Вот как именно.javaClass может сломать безопасность типа. Этот код компилируется, но прерывается во время выполнения:

open class Foo

class Bar : Foo() {
    val baz: Int = 0
}

fun main(args: Array<String>) {
    val someFoo: Foo = Bar()
    val anotherFoo: Foo = Foo()

    val someFooProperty: KProperty1<in Foo, *> = // 'in Foo' is bad
            someFoo.javaClass.kotlin.memberProperties.first()

    val someValue = someFooProperty.get(anotherFoo)
}

Этот пример используетkotlin-reflect.

Это потому чтоsomeFooProperty представляет собой собственностьBarнеFoo, но так как он был получен изsomeFoo.javaClass (Class<Foo> затем преобразуется вKClass<Foo>) компилятор позволяет нам использовать его сin Foo проекция.

Ваш ответ на вопрос