Reified у Kotlin-у — шта је то, синтакса и примена

Аутор: IT Sectr Објављено: 2026-06-21 Време читања: 8 мин

reified — кључна реч у језику Kotlin која омогућава приступ типу generic параметра унутар inline функције током извршавања. Код обичних generics-а делује type erasure — информација о типу се брише у фази компилације, али reified је чува. Према Kotlin Documentation, 2025, reified ради само унутар inline функција, јер компајлер замењује стварни тип у фази уграђивања.

Главне тачке

  • reified — модификатор generic параметра који чува информацију о типу у runtime-у
  • Inline only — reified ради искључиво унутар inline функција
  • Type erasure — стандардни механизам Java/Kotlin који брише generic типове; reified га заобилази
  • Провере is — могуће: if (value is T) уместо if (value is String)
  • Креирање инстанци — креирање T::class.java.newInstance() без прослеђивања Class

Шта је reified у Kotlin-у?

reified — модификатор generic параметра inline функције који чини тип стварним (reify — “овештаствља”) у runtime-у. Без 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 функција где је потребан тип у runtime-у — креирање инстанци, провере типа, добијање Class за рефлексију или серијализацију.

Проблем type erasure у generics-а

Type erasure — механизам Java и Kotlin-а код кога се информација о generic параметрима брише током компилације. У бајт-коду, List и List постају једноставно List. Ово је урађено ради уназадне компатибилности са Java 1.4, где generics нису постојали, али ствара ограничења при раду са типовима у runtime-у.

kotlin
// ❌ Грешка: Није могуће проверити инстанцу избрисаног типа
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, али ово захтева boilerplate: сваки позив је праћен са .java или ::class.java. reified у потпуности елиминише овај boilerplate.

Синтакса reified и механизам рада

Модификатор reified се поставља испред generic параметра у inline функцији. Функција мора обавезно бити inline — компајлер мора имати могућност замене конкретног типа у фази уграђивања.

kotlin
inline fun <reified T> isA(value: Any): Boolean {
    return value is T
}

fun main() {
    println(isA<String>("Здраво")) // true
    println(isA<Int>("Здраво"))  // false
}

Током компилације, позив isA("Hello") се замењује провером value is String. Позив isA("Hello") — провером value is Int. Тип се замењује буквално, што омогућава коришћење is, as, ::class и других операција недоступних код type erasure.

Декомпилација reified функције

Ако декомпајлирамо бајт-код isA("Hello"), IntelliJ IDEA ће приказати отприлике следећи резултат у Java-и: String.class.isInstance(value). Уместо generic параметра, компајлер је заменио конкретно java.lang.String.class — без рефлексије са претраживањем типа по имену, само директна референца на класу.

Провере типова са reified: is и as

Најчешћа примена reified-а — провера типа кроз оператор is. У обичној generic функцији value is T се не компајлира. Са reified-ом ово ради као са обичном класом: value is String, value is List (скоро — с обзиром на ограничења reified за параметризоване типове).

kotlin
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(list) са параметром Class. Са reified-ом, позив се чита као природна операција над листом, што побољшава читљивост ланаца обраде података.

Према подацима Kotlin Coroutines Guide (JetBrains, 2025), reified провере типа се користе у launch и async за пренос типа резултата корутине, што омогућава избегавање експлицитног навођења типа у већини случајева.

Рефлексија са reified: креирање инстанци и приступ Class-у

reified даје приступ T::class — референци на KClass, из које се може добити Java Class преко .java. Ово отвара могућности за креирање инстанци кроз рефлексију, рад са серијализаторима и добијање анотација класе током извршавања.

kotlin
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(json). Ово изгледа као мало побољшање, али у пројекту са стотинама позива серијализације, reified значајно смањује boilerplate и чини код чистијим.

Ограничења reified и алтернативе

reified има ограничења. Прво — ради само унутар inline функција. Ако функција не може да буде inline (на пример, рекурзивна је или превелика), reified није доступан. Друго — reified се не може користити директно са suspend функцијама, само кроз inline омотаче.

Треће — reified не ради у потпуности са параметризованим типовима. На пример, filterByType>() може дати неочекивани резултат, јер за параметризоване типове reified чува само сирови тип (List), без навођења generic аргумената. За потпуну проверу параметризованих типова потребна је рефлексија са TypeToken-ом.

ОперацијаСа reifiedБез reified
value is T✅ Ради❌ Грешка компилације
T::class✅ Ради❌ Грешка компилације
List is T⚠️ Само raw type❌ Грешка
Креирање инстанце✅ Кроз рефлексију❌ Потребан Class
Suspend функција❌ Само кроз inline омотач❌ Није применљиво

За случајеве када reified није доступан, користите образац са експлицитним прослеђивањем Class или TypeToken из библиотека (на пример, Gson TypeToken или Jackson TypeReference). Овај приступ ради у било којим функцијама, али захтева boilerplate и мање је погодан.

Често постављана питања

Зашто reified ради само са inline функцијама?

Компајлер замењује reified параметар T конкретним типом током уграђивања тела функције. Ако функција није inline, компајлер нема место где да замени тип — позив generic функције се одвија кроз јединствени бајт-код, где је T избрисан. Inline ствара посебну копију бајт-кода за сваки тип-аргумент.

Може ли се декларисати reified property?

Не, reified се примењује само на параметре функција. За својства се користи образац inline fun са повратном вредношћу или експлицитно прослеђивање Class кроз конструктор. Extension properties такође не подржавају reified.

Како reified ради са nullable типовима?

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 има overhead?

Минималан. reified не користи рефлексију — компајлер замењује конкретни тип у фази уграђивања. У бајт-коду ово је директна референца на класу (ldc + checkcast/invokevirtual). Нема overhead-а у поређењу са ручним прослеђивањем Class — оба варианта генеришу исти бајт-код.

Може ли се reified користити у Android развоју?

Да, reified се активно користи у Android-у. Bundle.getParcelable(), Intent.getSerializableExtra(), viewModels() из Android KTX — све ове функције користе reified да избегну експлицитно прослеђивање Class. Према подацима Google Android Docs (2025), reified се препоручује за generic API где је потребан тип у runtime-у.

Закључак

  • reified — модификатор generic параметра inline функције, чува тип у runtime-у
  • Type erasure — стандардни механизам брисања типова; reified га заобилази кроз уграђивање
  • is/as — провера и конверзија типова ради са reified као са обичним класама
  • Референца на класу — T::class и T::class.java су доступни за рефлексију и серијализацију
  • Само inline — reified је немогућ без inline функције због механизма замене типа
  • Параметризовани типови — reified не чува generic аргументе (само raw type)
  • Примена — Gson/Moshi серијализација, DI контејнери, провере типова у колекцијама, Android KTX

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође