reified — ключова дума в езика Kotlin, която позволява достъп до типа на generic параметър вътре в inline-функция по време на изпълнение. При обикновените generics действа type erasure — информацията за типа се изтрива на етапа на компилация, но reified я запазва. Според Kotlin Documentation, 2025, reified работи само вътре в inline-функции, тъй като компилаторът замества реалния тип на етапа на вграждане.
Основни точки
reified — модификатор на generic параметър на inline-функция, който прави типа реален (reify — “овеществява”) по време на изпълнение. Без reified типът T вътре в generic функция е недостъпен — компилаторът прилага type erasure, изтривайки цялата информация за типа. reified принуждава компилатора да замести конкретния тип на мястото на извикване, правейки го достъпен чрез T::class и оператора is.
Според Kotlin Survey by Kodee (2024), reified type parameters са сред десетте най-търсени функции на Kotlin — 52% от анкетираните разработчици ги използват, предимно за писане на generic фабрики, DI контейнери и сериализатори. Reified е особено популярен в комбинация с Gson, Moshi и Kotlinx Serialization.
Технически механизмът е прост: при извикване на inline-функция с reified параметър, компилаторът знае конкретния тип на аргумента (Int, String, User) и го замества на мястото на T. В байткода reified-параметърът се превръща в обикновен Class
Използвайте reified за писане на generic функции, където типът е необходим по време на изпълнение — създаване на инстанции, проверки на тип, получаване на Class
Type erasure — механизмът на Java и Kotlin, при който информацията за generic параметрите се изтрива по време на компилация. В байткода List
// ❌ Грешка: Не може да се провери инстанция на изтрит тип
fun <T> checkType(value: Any) {
if (value is T) { // type erasure — T е неизвестен
println("Типът съвпада")
}
}
// ✅ Solution: pass Class as parameter
fun <T> checkTypeWithClass(
value: Any,
clazz: Class<T>
) {
if (clazz.isInstance(value)) {
println("Типът съвпада")
}
}
В примера checkType не се компилира поради type erasure — компилаторът не знае какъв тип да замести на мястото на T. В checkTypeWithClass проблемът е решен чрез изрично предаване на Class
Модификаторът reified се поставя пред generic параметъра в inline-функция. Функцията трябва задължително да бъде inline — компилаторът трябва да има възможност да замести конкретния тип на етапа на вграждане.
inline fun <reified T> isA(value: Any): Boolean {
return value is T
}
fun main() {
println(isA<String>("Здравей")) // true
println(isA<Int>("Здравей")) // false
}
По време на компилация, извикването isA
Ако декомпилираме байткода на isA
Най-честото приложение на reified — проверка на тип чрез оператора is. В обикновена generic функция value is T не се компилира. С reified това работи като с обикновен клас: value is String, value is List
inline fun <reified T> List<Any>.filterByType(): List<T> {
return this.filter { it is T }.map { it as T }
}
val mixed = listOf("a", 1, "b", 2)
val strings = mixed.filterByType<String>() // ["a", "b"]
val ints = mixed.filterByType<Int>() // [1, 2]
Функцията за разширение filterByType филтрира списъка, оставяйки само елементи от посочения тип. Без reified трябваше да се пише filterByType
Според данни Kotlin Coroutines Guide (JetBrains, 2025), reified проверките на типове се използват в launch и async за предаване на типа на резултата от корутината, което позволява избягване на изричното посочване на тип в повечето случаи.
Reified предоставя достъп до T::class — препратка към KClass, от която може да се получи Java Class чрез .java. Това отваря възможности за създаване на инстанции чрез рефлексия, работа със сериализатори и получаване на анотации на класа по време на изпълнение.
inline fun <reified T> createInstance(): T =
T::class.java.getDeclaredConstructor().newInstance()
// Употреба
data class User(val name: String = "default")
val user = createInstance<User>()
// Сериализация с Gson
inline fun <reified T> Gson.fromJson(json: String): T =
this.fromJson(json, T::class.java)
// Получаване на анотации
inline fun <reified T> hasAnnotation<A>(): Boolean where A : Annotation =
T::class.java.isAnnotationPresent(A::class.java)
Обвивката fromJson за Gson — класически пример за използване на reified в продукция. Вместо gson.fromJson(json, User::class.java) може да се пише gson.fromJson
Reified има ограничения. Първо — работи само вътре в inline-функции. Ако функцията не може да бъде направена inline (например рекурсивна е или твърде голяма), reified не е достъпен. Второ — reified не може да се използва директно със suspend-функции, само чрез inline обвивки.
Трето — reified не работи напълно с параметризирани типове. Например filterByType>() може да даде неочакван резултат, тъй като за параметризирани типове reified запазва само суровия тип (List), без да посочва generic аргументите. За пълна проверка на параметризирани типове е необходима рефлексия с TypeToken.
| Операция | С reified | Без reified |
|---|---|---|
| value is T | ✅ Работи | ❌ Грешка при компилация |
| T::class | ✅ Работи | ❌ Грешка при компилация |
| List | ⚠️ Само raw type | ❌ Грешка |
| Създаване на инстанция | ✅ Чрез рефлексия | ❌ Нужен е Class |
| Suspend функция | ❌ Само чрез inline обвивка | ❌ Не е приложимо |
За случаите, когато reified не е достъпен, използвайте модела с изрично предаване на Class
Често задавани въпроси
Компилаторът заменя reified параметъра T с конкретния тип по време на вграждане на тялото на функцията. Ако функцията не е inline, компилаторът няма място, където да замести типа — извикването на generic функция става чрез единичен байткод, където T е изтрит. Inline създава отделно копие на байткода за всеки тип-аргумент.
Не, reified е приложим само към параметри на функции. За свойства се използва моделът inline fun
Reified поддържа nullable типове: reified T : Any (non-null) и просто reified T (може да бъде nullable). За nullable типове T::class връща класа за non-null версията (String::class за String?). Проверката value is T взема предвид null: ако T = String?, тогава null is T = true.
Минимален. Reified не използва рефлексия — компилаторът замества конкретния тип на етапа на вграждане. В байткода това е директно препращане към класа (ldc + checkcast/invokevirtual). Няма overhead в сравнение с ръчното предаване на Class
Да, reified се използва активно в Android. Bundle.getParcelable
Резюме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също