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 — 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
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
Type erasure — mecanismul Java și Kotlin prin care informația despre parametrii generici este ștearsă în timpul compilării. În bytecode, List
// ❌ 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
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.
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
Dacă decompilăm bytecode-ul isA
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
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
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.
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.
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
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ția | Cu reified | Fără reified |
|---|---|---|
| value is T | ✅ Funcționează | ❌ Eroare de compilare |
| T::class | ✅ Funcționează | ❌ Eroare de compilare |
| List | ⚠️ 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
Întrebări frecvente
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.
Nu, reified se aplică doar parametrilor funcțiilor. Pentru proprietăți se utilizează pattern-ul inline fun
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.
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
Da, reified este utilizat activ în Android. Bundle.getParcelable
Rezumat
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.
Citiți și