Reified în Kotlin — ce este, sintaxa și aplicarea

Autor: IT Sectr Publicat: 2026-06-21 Timp de citire: 8 min

reified — cuvânt cheie în limbajul Kotlin care permite accesul la tipul parametrului generic în interiorul unei funcții inline în timpul execuției. În genericele obișnuite funcționează type erasure — informația despre tip este ștearsă în faza de compilare, dar reified o păstrează. Conform Kotlin Documentation, 2025, reified funcționează doar în interiorul funcțiilor inline, deoarece compilatorul substituie tipul real în faza de încorporare.

Principalele puncte

  • reified — modificator al parametrului generic care păstrează informația despre tip în runtime
  • Inline only — reified funcționează exclusiv în interiorul funcțiilor inline
  • Type erasure — mecanismul standard Java/Kotlin care șterge tipurile generice; reified îl ocolește
  • Verificări is — posibile: if (value is T) în loc de if (value is String)
  • Crearea instanțelor — crearea T::class.java.newInstance() fără transmiterea Class

Ce este reified în Kotlin?

reified — este un modificator al parametrului generic al unei funcții inline care face tipul real (reify — “concretizează”) în runtime. Fără reified, tipul T în interiorul funcției generice este inaccesibil — compilatorul aplică type erasure, ștergând toată informația despre tip. reified forțează compilatorul să substituie tipul concret în locul apelului, făcându-l accesibil prin T::class și operatorul is.

Conform Kotlin Survey by Kodee (2024), reified type parameters se află în primele zece cele mai căutate caracteristici Kotlin — le folosesc 52% dintre dezvoltatorii chestionați, în principal pentru scrierea de fabrici generice, containere DI și serializatoare. Reified este deosebit de popular în combinație cu Gson, Moshi și Kotlinx Serialization.

Din punct de vedere tehnic, mecanismul este simplu: la apelarea unei funcții inline cu parametru reified, compilatorul cunoaște tipul concret al argumentului (Int, String, User) și îl substituie în locul lui T. În bytecode, parametrul reified se transformă într-un simplu Class, transmis ca argument ascuns.

Utilizați reified pentru scrierea funcțiilor generice în care este necesar tipul în runtime — crearea instanțelor, verificări de tip, obținerea Class pentru reflecție sau serializare.

Problema type erasure în generice

Type erasure — mecanismul Java și Kotlin prin care informația despre parametrii generici este ștearsă în timpul compilării. În bytecode, List și List devin pur și simplu List. Acest lucru a fost făcut pentru compatibilitatea inversă cu Java 1.4, unde genericele nu existau, dar creează limitări când se lucrează cu tipuri în runtime.

kotlin
// ❌ Eroare: Nu se poate verifica instanța tipului șters
fun <T> checkType(value: Any) {
    if (value is T) { // type erasure — T este necunoscut
        println("Tipul se potrivește")
    }
}

// ✅ Solution: pass Class as parameter
fun <T> checkTypeWithClass(
    value: Any,
    clazz: Class<T>
) {
    if (clazz.isInstance(value)) {
        println("Tipul se potrivește")
    }
}

În exemplu, checkType nu se compilează din cauza type erasure — compilatorul nu știe ce tip să substituie în locul lui T. În checkTypeWithClass problema a fost rezolvată prin transmiterea explicită a Class, dar aceasta necesită boilerplate: fiecare apel este însoțit de .java sau ::class.java. reified elimină complet acest boilerplate.

Sintaxa reified și mecanismul de funcționare

Modificatorul reified se pune înaintea parametrului generic într-o funcție inline. Funcția trebuie să fie obligatoriu inline — compilatorul trebuie să aibă posibilitatea de a substitui tipul concret în faza de încorporare.

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

fun main() {
    println(isA<String>("Bună")) // true
    println(isA<Int>("Bună"))  // false
}

În timpul compilării, apelul isA("Hello") este înlocuit cu verificarea value is String. Apelul isA("Hello") — cu value is Int. Tipul este substituit literal, ceea ce permite utilizarea is, as, ::class și a altor operații inaccesibile cu type erasure.

Decompilarea funcției reified

Dacă decompilăm bytecode-ul isA("Hello"), IntelliJ IDEA va afișa aproximativ următorul rezultat în Java: String.class.isInstance(value). În locul parametrului generic, compilatorul a substituit java.lang.String.class concret — nicio reflecție cu căutarea tipului după nume, doar o referință directă la clasă.

Verificări de tip cu reified: is și as

Cea mai frecventă aplicare a reified — verificarea tipului prin operatorul is. Într-o funcție generică obișnuită, value is T nu se compilează. Cu reified funcționează ca cu o clasă obișnuită: value is String, value is List (aproape — ținând cont de limitările reified pentru tipurile parametrizate).

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]

Funcția de extensie filterByType filtrează lista, păstrând doar elementele tipului specificat. Fără reified ar trebui să scriem filterByType(list) cu parametrul Class. Cu reified, apelul se citește ca o operație naturală asupra listei, ceea ce îmbunătățește lizibilitatea lanțurilor de procesare a datelor.

Conform datelor Kotlin Coroutines Guide (JetBrains, 2025), verificările de tip reified sunt utilizate în launch și async pentru transmiterea tipului rezultatului coroutinei, ceea ce permite evitarea specificării explicite a tipului în majoritatea cazurilor.

Reflecție cu reified: crearea instanțelor și accesul la Class

reified oferă acces la T::class — o referință la KClass, din care se poate obține Java Class prin .java. Aceasta deschide posibilități pentru crearea instanțelor prin reflecție, lucrul cu serializatoare și obținerea adnotărilor clasei în timpul execuției.

kotlin
inline fun <reified T> createInstance(): T =
    T::class.java.getDeclaredConstructor().newInstance()

// Utilizare
data class User(val name: String = "default")
val user = createInstance<User>()

// Serializare cu Gson
inline fun <reified T> Gson.fromJson(json: String): T =
    this.fromJson(json, T::class.java)

// Obținerea adnotărilor
inline fun <reified T> hasAnnotation<A>(): Boolean where A : Annotation =
    T::class.java.isAnnotationPresent(A::class.java)

Wrapper-ul fromJson pentru Gson — un exemplu clasic de utilizare a reified în producție. În loc de gson.fromJson(json, User::class.java) se poate scrie gson.fromJson(json). Pare o îmbunătățire minoră, dar într-un proiect cu sute de apeluri de serializare, reified reduce semnificativ boilerplate-ul și face codul mai curat.

Limitări ale reified și alternative

reified are limitări. Prima — funcționează doar în interiorul funcțiilor inline. Dacă funcția nu poate fi făcută inline (de exemplu, este recursivă sau prea mare), reified nu este disponibil. A doua — reified nu poate fi utilizat direct cu funcțiile suspend, ci doar prin wrapper-e inline.

A treia — reified nu funcționează complet cu tipurile parametrizate. De exemplu, filterByType>() poate da un rezultat neașteptat, deoarece pentru tipurile parametrizate reified păstrează doar tipul brut (List), fără specificarea argumentelor generice. Pentru verificarea completă a tipurilor parametrizate este necesară reflecția cu TypeToken.

OperațiaCu reifiedFără reified
value is T✅ Funcționează❌ Eroare de compilare
T::class✅ Funcționează❌ Eroare de compilare
List is T⚠️ Doar raw type❌ Eroare
Crearea instanței✅ Prin reflecție❌ Necesită Class
Funcția Suspend❌ Doar prin wrapper inline❌ Nu se aplică

Pentru cazurile în care reified nu este disponibil, utilizați pattern-ul cu transmiterea explicită a Class sau a TypeToken din biblioteci (de exemplu, Gson TypeToken sau Jackson TypeReference). Această abordare funcționează în orice funcții, dar necesită boilerplate și este mai puțin convenabilă.

Întrebări frecvente

De ce reified funcționează doar cu funcțiile inline?

Compilatorul înlocuiește parametrul reified T cu tipul concret în timpul încorporării corpului funcției. Dacă funcția nu este inline, compilatorul nu are locul unde să substituie tipul — apelul funcției generice are loc printr-un bytecode unitar, unde T este șters. Inline creează o copie separată de bytecode pentru fiecare tip-argument.

Se poate declara o proprietate reified?

Nu, reified se aplică doar parametrilor funcțiilor. Pentru proprietăți se utilizează pattern-ul inline fun cu returnarea valorii sau transmiterea explicită a Class prin constructor. Extension properties nu suportă reified.

Cum funcționează reified cu tipurile nullable?

reified suportă tipurile nullable: reified T : Any (non-null) și simplu reified T (poate fi nullable). Pentru tipurile nullable, T::class returnează clasa pentru versiunea non-null (String::class pentru String?). Verificarea value is T ține cont de null: dacă T = String?, atunci null is T = true.

Are reified overhead?

Minim. reified nu utilizează reflecție — compilatorul substituie tipul concret în faza de încorporare. În bytecode, aceasta este o referință directă la clasă (ldc + checkcast/invokevirtual). Nu există overhead în comparație cu transmiterea manuală a Class — ambele variante generează același bytecode.

Se poate utiliza reified în dezvoltarea Android?

Da, reified este utilizat activ în Android. Bundle.getParcelable(), Intent.getSerializableExtra(), viewModels() din Android KTX — toate aceste funcții folosesc reified pentru a evita transmiterea explicită a Class. Conform datelor Google Android Docs (2025), reified este recomandat pentru API-uri generice unde este necesar tipul în runtime.

Rezumat

  • reified — modificator al parametrului generic al funcției inline care păstrează tipul în runtime
  • Type erasure — mecanismul standard de ștergere a tipurilor; reified îl ocolește prin încorporare
  • is/as — verificarea și conversia tipurilor funcționează cu reified ca și cu clasele obișnuite
  • Referință la clasă — T::class și T::class.java sunt disponibile pentru reflecție și serializare
  • Doar inline — reified este imposibil fără funcția inline din cauza mecanismului de substituire a tipului
  • Tipuri parametrizate — reified nu păstrează argumentele generice (doar raw type)
  • Aplicare — serializare Gson/Moshi, containere DI, verificări de tip în colecții, Android KTX

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și