Отражение Котлина: параметр неизвестного типа

Я провожу несколько экспериментов над отражением Котлина.

Я пытаюсь получить объект отражения общего класса с его аргументом.

В Java это будет ParameterizedType .

Способ получить такое, используя API отражения Java, немного запутан: создать анонимный подкласс общего класса, а затем получить его первый тип супертипа.

Вот пример:

 @Suppress("unused") @PublishedApi internal abstract class TypeReference<T> {} inline fun <reified T> jGeneric() = ((object : TypeReference<T>() {}).javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] 

Когда я println(jGeneric<List<String?>>()) , он печатает java.util.List<? extends java.lang.String> java.util.List<? extends java.lang.String> , что логично, учитывая, что в List Kotlin List используется дисперсия объявления-сайта и что типы Java не имеют понятия об ошибке.

Теперь я хотел бы добиться такого же результата, но с API-интерфейсом Kotlin reflection (который, конечно, содержал бы информацию об отсутствии).

Конечно, List<String>::class не может работать, так как он дает KClass . и я ищу KType .

Однако, когда я пробую это:

 inline fun <reified T> kGeneric() = (object : TypeReference<T>() {})::class.supertypes[0].arguments[0].type 

Когда я println(kGeneric<List<String?>>()) , он печатает [ERROR : Unknown type parameter 0] , что довольно … хорошо, антиклиматично;)

Как я могу получить в Kotlin KType отражающий List<String> ?

Чтобы создать экземпляр KType в Kotlin 1.1, у вас есть два варианта:

  • Чтобы создать простой тип, не содержащий KClass , из класса KClass , где класс либо не является общим, либо вы можете заменить все его параметры типа звездообразными проекциями ( * ), используйте свойство starProjectedType . Например, следующее создает KType представляющий тип с KType значением String :

     val nonNullStringType = String::class.starProjectedType 

    Или следующее создает KType представляющий список с недействительным типом List<*> :

     val nonNullListOfSmth = List::class.starProjectedType 
  • Для более сложных случаев используйте функцию createType . Он принимает аргументы класса, типа и должен ли тип быть нулевым. Аргументы типа представляют собой список KTypeProjection который является просто дисперсией типа + (in / out / none). Например, следующий код создает экземпляр KType представляющий List<String> :

     val nonNullStringType = String::class.starProjectedType val projection = KTypeProjection.invariant(nonNullStringType) val listOfStrings = listClass.createType(listOf(projection)) 

    Или, следующий создает тип List<String>? :

     val listOfStrings = listClass.createType(listOf(projection), nullable = true) 

Оба типа starProjectedType и createType определены в пакете kotlin.reflect.full .

Мы планируем ввести возможность получения экземпляра KType просто из параметра типа KType встроенной функции, которая помогла бы в некоторых случаях, когда необходимый тип известен статически, однако в настоящее время не совсем ясно, возможно ли это без больших издержек. Итак, до тех пор, пока это не будет выполнено, используйте приведенные выше объявления.

Intereting Posts
Android Как установить множественные значения гравитации программно в Котлин? не родной брат в том же RelativeLayout? Android: кнопка на фрагменте Ошибка – невозможно изменить заголовок supportActionBar В Котлине, как мне типа groupBy Тест Running Spek показывает ошибку "Empty test suite" Котлин «Смарт-литье невозможно, потому что к этому моменту собственность могла быть изменена» Пользовательский десериализатор для любого списка в Джексоне Как разделить строку с набором разделителей и найти, что это за разделитель? Котлин Почему Spring-data-elasticsearch не использует объект-образец из весеннего контекста error: Parceler: невозможно найти генератор чтения / записи для типа io.realm.RealmList Параметр аннотированного типа в Java для компилятора Kotlin Как получить доступ и передать параметры модулям Android Instant App Как заставить компилятор Kotlin рассматривать предупреждения как ошибки? Программно раздутый макет с расширениями Android Kotlin