Стирание типов и параметры типов reified
Используйте reified с inline-функциями для доступа к информации о типах во время выполнения.
«Стирание типов и параметры типов reified» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.
Что такое стирание типов
Во время выполнения JVM стирает аргументы обобщённых типов. List<String> и List<Int> оба превращаются просто в List. Это ограничивает операции с обобщёнными типами во время выполнения.
fun main() {
val strings: List<String> = listOf("a", "b")
val ints: List<Int> = listOf(1, 2)
println(strings.javaClass == ints.javaClass) // true: both ArrayList
println(strings is List<*>) // OK with star
// println(strings is List<String>) // warning: unchecked cast
}Проблема: стёртые типы нельзя проверить
Нельзя использовать is с конкретным аргументом обобщённого типа, потому что информация о типе исчезает во время выполнения.
fun checkType(obj: Any) {
// This works:
if (obj is List<*>) println("It's a list of something")
// This doesn't compile cleanly:
// if (obj is List<String>) println("It's a list of strings") // unchecked
}
fun main() {
checkType(listOf("hello"))
checkType(42)
}Итоги по функциям inline
inline копирует тело функции в место вызова во время компиляции. Именно это делает возможным использование reified: аргумент типа также подставляется в месте вызова.
inline fun <T> myRun(block: () -> T): T = block()
fun main() {
val result = myRun { 42 }
println(result) // 42
// The compiler inlines the lambda body — no object allocation
}reified: доступ к T во время выполнения
Сочетание inline и reified сохраняет аргумент типа в месте вызова, позволяя использовать is, as и ::class с T.
inline fun <reified T> isInstance(value: Any): Boolean = value is T
fun main() {
println(isInstance<String>("hello")) // true
println(isInstance<Int>("hello")) // false
println(isInstance<List<*>>(listOf())) // true
}Получение KClass для T
С помощью reified T можно получить T::class во время выполнения — обычно это невозможно в обобщённых функциях.
inline fun <reified T> classNameOf(): String = T::class.simpleName ?: "Unknown"
fun main() {
println(classNameOf<String>()) // String
println(classNameOf<Int>()) // Int
println(classNameOf<List<*>>()) // List
}Безопасное приведение с reified
Используйте reified, чтобы написать типобезопасную утилиту приведения, которая возвращает пустое значение вместо выбрасывания исключения.
inline fun <reified T> Any?.safeCast(): T? = this as? T
fun main() {
val obj: Any = "Hello"
val s: String? = obj.safeCast<String>()
val i: Int? = obj.safeCast<Int>()
println(s) // Hello
println(i) // null
}Разбор JSON с reified
Библиотеки вроде Gson или kotlinx.serialization используют reified, чтобы вывести целевой тип в месте вызова без явной передачи объектов Class.
import com.google.gson.Gson
// Simulated without real Gson:
inline fun <reified T> parseJson(json: String): T {
return Gson().fromJson(json, T::class.java)
}
// Usage:
// val user: User = parseJson<User>("""{"name":"Alice"}""")reified с filterIsInstance
filterIsInstance<T>() из стандартной библиотеки использует reified, чтобы отфильтровать список по конкретному типу без ручного приведения.
fun main() {
val mixed: List<Any> = listOf(1, "hello", 2.5, "world", true)
val strings = mixed.filterIsInstance<String>()
val ints = mixed.filterIsInstance<Int>()
println(strings) // [hello, world]
println(ints) // [1]
}Нельзя использовать reified в функциях без inline
reified работает только с функциями inline. Попытка использовать его без inline приводит к ошибке компиляции.
// Error:
// fun <reified T> broken(): String = T::class.simpleName ?: "?"
// Must be inline:
inline fun <reified T> correct(): String = T::class.simpleName ?: "?"
fun main() {
println(correct<Double>()) // Double
}reified и отражение
Сочетайте reified с отражением, чтобы динамически проверять свойства или аннотации типа без шаблонных параметров Class.
inline fun <reified T : Any> properties(): List<String> =
T::class.members.map { it.name }
data class Point(val x: Int, val y: Int)
fun main() {
println(properties<Point>()) // [x, y, component1, component2, copy, equals, hashCode, toString]
}Практика: типобезопасный локатор сервисов
Используйте reified, чтобы создать локатор сервисов, сопоставляющий KClass с экземплярами для облегчённого DI без процессоров аннотаций.
val registry = mutableMapOf<kotlin.reflect.KClass<*>, Any>()
inline fun <reified T : Any> register(instance: T) { registry[T::class] = instance }
@Suppress("UNCHECKED_CAST")
inline fun <reified T : Any> resolve(): T = registry[T::class] as T
class Logger { fun log(msg: String) = println("[LOG] $msg") }
fun main() {
register(Logger())
resolve<Logger>().log("Service located!")
}Ограничения reified
Параметры типа reified нельзя использовать в контекстах без inline, нельзя сохранить для последующего использования и нельзя передать в функции без inline, которым нужен тип во время выполнения.
inline fun <reified T> foo() {
val clazz = T::class // OK here
// bar(clazz) // must pass clazz explicitly to non-inline funs
println(clazz.simpleName)
}
fun bar(clazz: kotlin.reflect.KClass<*>) = println(clazz.simpleName)
fun main() { foo<String>() }Быстрая проверка
Что требуется, чтобы параметр типа стал reified?
Итоги
Стирание типов удаляет информацию об обобщённых типах во время выполнения. reified у функций inline сохраняет аргумент типа в месте вызова, позволяя использовать is, as, ::class и отражение с T — без ручной передачи объектов Class.
Часто задаваемые вопросы
Урок «Стирание типов и параметры типов reified» бесплатный?
Да — полный текст урока «Стирание типов и параметры типов reified» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.
Чему я научусь в уроке «Стирание типов и параметры типов reified»?
Используйте reified с inline-функциями для доступа к информации о типах во время выполнения. Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Kotlin Academy?
Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Стирание типов и параметры типов reified»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Kotlin Academy?
Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Обобщённые функции и ограничения типов с where
- Вариативность на месте объявления: in и out
- Звёздная проекция и случаи применения *
- Стирание типов и параметры типов reified