0Pricing
Kotlin Academy · Урок

Стирание типов и параметры типов 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 — локальная установка не требуется.

Все уроки этого курса

  1. Обобщённые функции и ограничения типов с where
  2. Вариативность на месте объявления: in и out
  3. Звёздная проекция и случаи применения *
  4. Стирание типов и параметры типов reified
← Назад к Kotlin Academy