Reified a Kotlinban — mi ez, szintaxis és alkalmazás

Szerző: IT Sectr Megjelenés: 2026-06-21 Olvasási idő: 8 perc

reified — kulcsszó a Kotlin nyelvben, amely lehetővé teszi a generic paraméter típusának elérését egy inline-függvényen belül futásidőben. A szokásos generics-nél type erasure működik — a típusra vonatkozó információ törlődik a fordítási fázisban, de a reified megőrzi azt. A Kotlin Documentation, 2025 szerint a reified csak inline-függvényeken belül működik, mivel a fordító behelyettesíti a valós típust a beágyazás fázisában.

Főbb pontok

  • reified — a generic paraméter módosítója, amely megőrzi a típusra vonatkozó információt futásidőben
  • Inline only — a reified kizárólag inline-függvényeken belül működik
  • Type erasure — a Java/Kotlin szabványos mechanizmusa, amely törli a generic típusokat; a reified megkerüli azt
  • is ellenőrzések — lehetségesek: if (value is T) az if (value is String) helyett
  • Példányok létrehozása — T::class.java.newInstance() létrehozása Class átadása nélkül

Mi az a reified a Kotlinban?

reified — egy inline-függvény generic paraméterének módosítója, amely valóssá teszi a típust (reify — “megvalósít”) futásidőben. reified nélkül a T típus a generic függvényen belül nem érhető el — a fordító type erasure-t alkalmaz, törölve minden információt a típusról. reified arra kényszeríti a fordítót, hogy a konkrét típust a hívás helyén behelyettesítse, elérhetővé téve azt a T::class és az is operátor segítségével.

A Kotlin Survey by Kodee (2024) szerint a reified type parameters a tíz legkeresettebb Kotlin funkció közé tartozik — a megkérdezett fejlesztők 52%-a használja, főként generic gyárak, DI konténerek és szerializálók írásához. A reified különösen népszerű a Gson, Moshi és Kotlinx Serialization kombinációjával.

Technikailag a mechanizmus egyszerű: egy reified paraméterrel rendelkező inline-függvény meghívásakor a fordító ismeri az argumentum konkrét típusát (Int, String, User), és behelyettesíti a T helyére. A bájtkódban a reified-paraméter egy szokásos Class-vé alakul, amely rejtett argumentumként kerül átadásra.

Használja a reified-et olyan generic függvények írásához, ahol futásidőben szükség van a típusra — példányok létrehozása, típusellenőrzés, Class megszerzése reflexióhoz vagy szerializációhoz.

A type erasure problémája a generics-ben

Type erasure — a Java és Kotlin mechanizmusa, amelynél a generic paraméterekre vonatkozó információ törlődik a fordítás során. A bájtkódban a List és a List egyszerűen List-té válik. Ez a Java 1.4-gyel való visszafelé kompatibilitás érdekében történt, ahol nem voltak generics-ek, de korlátozásokat hoz létre a típusokkal való futásidőbeli munkában.

kotlin
// ❌ Hiba: Nem ellenőrizhető a törölt típus példánya
fun <T> checkType(value: Any) {
    if (value is T) { // type erasure — T ismeretlen
        println("Típus egyezik")
    }
}

// ✅ Solution: pass Class as parameter
fun <T> checkTypeWithClass(
    value: Any,
    clazz: Class<T>
) {
    if (clazz.isInstance(value)) {
        println("Típus egyezik")
    }
}

A példában a checkType nem fordul le a type erasure miatt — a fordító nem tudja, milyen típust helyettesítsen a T helyére. A checkTypeWithClass esetében a probléma a Class explicit átadásával megoldódott, de ez boilerplate-et igényel: minden hívást .java vagy ::class.java kísér. A reified teljesen megszünteti ezt a boilerplate-et.

A reified szintaxisa és működési mechanizmusa

A reified módosító a generic paraméter előtt áll egy inline-függvényben. A függvénynek kötelezően inline-nak kell lennie — a fordítónak rendelkeznie kell a konkrét típus behelyettesítésének lehetőségével a beágyazás fázisában.

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

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

A fordítás során az isA("Hello") hívás a value is String ellenőrzéssel helyettesítődik. Az isA("Hello") hívás — a value is Int ellenőrzéssel. A típus szó szerint behelyettesítődik, ami lehetővé teszi az is, as, ::class és más műveletek használatát, amelyek a type erasure esetén nem elérhetők.

A reified függvény dekompilálása

Ha dekompiláljuk az isA("Hello") bájtkódját, az IntelliJ IDEA körülbelül a következő eredményt mutatja Java-ban: String.class.isInstance(value). A generic paraméter helyett a fordító a konkrét java.lang.String.class-t helyettesítette — nincs reflexió a típus név szerinti keresésével, csak közvetlen hivatkozás az osztályra.

Típusellenőrzések reified-del: is és as

A reified leggyakoribb alkalmazása — típusellenőrzés az is operátoron keresztül. Egy szokásos generic függvényben a value is T nem fordul le. A reified-del ez úgy működik, mint egy szokásos osztály esetében: value is String, value is List (majdnem — figyelembe véve a reified korlátait a paraméterezett típusoknál).

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]

A filterByType kiterjesztő függvény szűri a listát, csak a megadott típus elemeit hagyva meg. reified nélkül a filterByType(list) függvényt kellene írni a Class paraméterrel. A reified-del a hívás természetes listaműveletként olvasható, ami javítja az adatfeldolgozási láncok olvashatóságát.

Az adatok szerint Kotlin Coroutines Guide (JetBrains, 2025), a reified típusellenőrzéseket a launch és async függvényekben használják a korutin eredménytípusának átadására, ami lehetővé teszi a típus explicit megadásának elkerülését a legtöbb esetben.

Reflexió reified-del: példányok létrehozása és hozzáférés a Class-hoz

A reified hozzáférést biztosít a T::class-hoz — egy KClass-ra való hivatkozáshoz, amelyből a .java segítségével Java Class nyerhető. Ez lehetőségeket nyit a példányok reflexió általi létrehozására, a szerializálókkal való munkára és az osztályannotációk futásidőben történő lekérésére.

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

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

// Szerializáció Gson-nal
inline fun <reified T> Gson.fromJson(json: String): T =
    this.fromJson(json, T::class.java)

// Annotációk lekérése
inline fun <reified T> hasAnnotation<A>(): Boolean where A : Annotation =
    T::class.java.isAnnotationPresent(A::class.java)

A fromJson wrapper a Gson számára — klasszikus példa a reified használatára éles környezetben. A gson.fromJson(json, User::class.java) helyett írható gson.fromJson(json). Ez kis fejlesztésnek tűnik, de egy több száz szerializációs hívással rendelkező projektben a reified jelentősen csökkenti a boilerplate-et és tisztábbá teszi a kódot.

A reified korlátai és alternatívák

A reified-nek vannak korlátai. Első — csak inline-függvényeken belül működik. Ha a függvény nem tehető inline-ná (például rekurzív vagy túl nagy), a reified nem érhető el. Második — a reified nem használható közvetlenül suspend-függvényekkel, csak inline wrappereken keresztül.

Harmadik — a reified nem működik teljes mértékben a paraméterezett típusokkal. Például a filterByType>() váratlan eredményt adhat, mivel a paraméterezett típusok esetén a reified csak a nyers típust (List) őrzi meg, a generic argumentumok megadása nélkül. A paraméterezett típusok teljes ellenőrzéséhez TypeToken-nel történő reflexió szükséges.

MűveletReified-delReified nélkül
value is T✅ Működik❌ Fordítási hiba
T::class✅ Működik❌ Fordítási hiba
List is T⚠️ Csak raw type❌ Hiba
Példány létrehozása✅ Reflexióval❌ Class szükséges
Suspend függvény❌ Csak inline wrapperen keresztül❌ Nem alkalmazható

Azokban az esetekben, amikor a reified nem érhető el, használja a Class vagy a könyvtárakból származó TypeToken explicit átadásának mintáját (például Gson TypeToken vagy Jackson TypeReference). Ez a megközelítés bármilyen függvényben működik, de boilerplate-et igényel és kevésbé kényelmes.

Gyakran ismételt kérdések

Miért működik a reified csak inline-függvényekkel?

A fordító a reified T paramétert a konkrét típussal helyettesíti a függvény törzsének beágyazása során. Ha a függvény nem inline, a fordítónak nincs helye a típus behelyettesítésére — a generic függvény hívása egységes bájtkódon keresztül történik, ahol a T törlődött. Inline külön bájtkód-másolatot hoz létre minden típus-argumentumhoz.

Lehet-e reified property-t deklarálni?

Nem, a reified csak függvényparaméterekre alkalmazható. Tulajdonságok esetén az inline fun minta használatos visszatérési értékkel, vagy a Class explicit átadása a konstruktoron keresztül. Az extension properties szintén nem támogatják a reified-et.

Hogyan működik a reified a nullable típusokkal?

A reified támogatja a nullable típusokat: reified T : Any (non-null) és egyszerűen reified T (lehet nullable). A nullable típusok esetén a T::class a non-null verzióhoz tartozó osztályt adja vissza (String::class a String? esetén). A value is T ellenőrzés figyelembe veszi a null-t: ha T = String?, akkor null is T = true.

Van overhead-je a reified-nek?

Minimális. A reified nem használ reflexiót — a fordító a konkrét típust a beágyazás fázisában helyettesíti be. A bájtkódban ez közvetlen hivatkozás az osztályra (ldc + checkcast/invokevirtual). Nincs overhead a Class kézi átadásához képest — mindkét variáns ugyanazt a bájtkódot generálja.

Használható-e a reified Android fejlesztésben?

Igen, a reified aktívan használatos Androidban. Bundle.getParcelable(), Intent.getSerializableExtra(), viewModels() az Android KTX-ből — mindezek a függvények reified-et használnak a Class explicit átadásának elkerülésére. Az adatok szerint Google Android Docs (2025), a reified ajánlott olyan generic API-hoz, ahol futásidőben szükség van a típusra.

Összefoglalás

  • reified — az inline-függvény generic paraméterének módosítója, megőrzi a típust futásidőben
  • Type erasure — a típusok törlésének szabványos mechanizmusa; a reified beágyazással megkerüli azt
  • is/as — típusellenőrzés és -konverzió a reified-del úgy működik, mint a szokásos osztályokkal
  • Osztályhivatkozás — a T::class és a T::class.java elérhető reflexióhoz és szerializációhoz
  • Csak inline — a reified nem lehetséges inline-függvény nélkül a típusbehelyettesítés mechanizmusa miatt
  • Paraméterezett típusok — a reified nem őrzi meg a generic argumentumokat (csak raw type)
  • Alkalmazás — Gson/Moshi szerializáció, DI konténerek, típusellenőrzések kollekciókban, Android KTX

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is