Reified in Kotlin — wat is het, syntaxis en toepassing

Auteur: IT Sectr Gepubliceerd: 2026-06-21 Leestijd: 8 min

reified — een sleutelwoord in de taal Kotlin waarmee je toegang krijgt tot het type van een generic-parameter binnen een inline-functie tijdens de uitvoering. Bij gewone generics werkt type erasure — informatie over het type wordt gewist tijdens de compilatiefase, maar reified behoudt het. Volgens Kotlin Documentation, 2025, werkt reified alleen binnen inline-functies, omdat de compiler het werkelijke type substitueert tijdens de inlining-fase.

Belangrijkste punten

  • reified — modifier van de generic-parameter die informatie over het type bewaart in runtime
  • Inline only — reified werkt uitsluitend binnen inline-functies
  • Type erasure — het standaardmechanisme van Java/Kotlin dat generic-types wist; reified omzeilt het
  • is-controles — mogelijk: if (value is T) in plaats van if (value is String)
  • Instanties maken — T::class.java.newInstance() maken zonder Class door te geven

Wat is reified in Kotlin?

reified — is een modifier van de generic-parameter van een inline-functie die het type echt maakt (reify — “verwezenlijken”) in runtime. Zonder reified is het type T binnen een generic-functie niet toegankelijk — de compiler past type erasure toe en wist alle informatie over het type. reified dwingt de compiler om het concrete type op de aanroepplaats te substitueren, waardoor het toegankelijk wordt via T::class en de operator is.

Volgens Kotlin Survey by Kodee (2024) behoren reified type parameters tot de tien meest gevraagde Kotlin-functies — 52% van de ondervraagde ontwikkelaars gebruikt ze, voornamelijk voor het schrijven van generic-fabrieken, DI-containers en serializers. Reified is vooral populair in combinatie met Gson, Moshi en Kotlinx Serialization.

Technisch gezien is het mechanisme eenvoudig: bij het aanroepen van een inline-functie met een reified parameter kent de compiler het concrete type van het argument (Int, String, User) en substitueert het in plaats van T. In bytecode wordt de reified-parameter omgezet in een gewone Class, doorgegeven als een verborgen argument.

Gebruik reified voor het schrijven van generic-functies waarbij het type in runtime nodig is — instanties maken, typecontroles, Class verkrijgen voor reflectie of serialisatie.

Het probleem van type erasure in generics

Type erasure — het mechanisme van Java en Kotlin waarbij informatie over generic-parameters wordt gewist tijdens de compilatie. In bytecode worden List en List gewoon List. Dit is gedaan voor achterwaartse compatibiliteit met Java 1.4, waar generics niet bestonden, maar creëert beperkingen bij het werken met typen in runtime.

kotlin
// ❌ Fout: Kan instantie van gewist type niet controleren
fun <T> checkType(value: Any) {
    if (value is T) { // type erasure — T is onbekend
        println("Type komt overeen")
    }
}

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

In het voorbeeld compileert checkType niet vanwege type erasure — de compiler weet niet welk type in plaats van T te substitueren. In checkTypeWithClass is het probleem opgelost door Class expliciet door te geven, maar dit vereist boilerplate: elke aanroep gaat gepaard met .java of ::class.java. reified elimineert deze boilerplate volledig.

Syntaxis van reified en werkingsmechanisme

De modifier reified wordt voor de generic-parameter in een inline-functie geplaatst. De functie moet verplicht inline zijn — de compiler moet de mogelijkheid hebben om het concrete type te substitueren tijdens de inlining-fase.

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

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

Tijdens de compilatie wordt de aanroep isA("Hello") vervangen door de controle value is String. De aanroep isA("Hello") — door value is Int. Het type wordt letterlijk gesubstitueerd, wat het gebruik mogelijk maakt van is, as, ::class en andere bewerkingen die niet beschikbaar zijn bij type erasure.

Decompilatie van een reified-functie

Als we de bytecode van isA("Hello") decompileren, toont IntelliJ IDEA ongeveer het volgende resultaat in Java: String.class.isInstance(value). In plaats van de generic-parameter heeft de compiler concreet java.lang.String.class gesubstitueerd — geen reflectie met het zoeken naar een type op naam, alleen een directe verwijzing naar de klasse.

Typecontroles met reified: is en as

De meest voorkomende toepassing van reified — typecontrole via de operator is. In een gewone generic-functie compileert value is T niet. Met reified werkt dit als met een gewone klasse: value is String, value is List (bijna — rekening houdend met de beperkingen van reified voor geparametriseerde typen).

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]

De extensiefunctie filterByType filtert de lijst en laat alleen elementen van het opgegeven type over. Zonder reified zou men filterByType(list) moeten schrijven met de parameter Class. Met reified leest de aanroep als een natuurlijke bewerking op de lijst, wat de leesbaarheid van gegevensverwerkingsketens verbetert.

Volgens gegevens uit de Kotlin Coroutines Guide (JetBrains, 2025) worden reified typecontroles gebruikt in launch en async voor het doorgeven van het resultaattype van de coroutine, waardoor expliciete typering in de meeste gevallen wordt vermeden.

Reflectie met reified: instanties maken en toegang tot Class

reified geeft toegang tot T::class — een verwijzing naar KClass, waaruit via .java de Java Class kan worden verkregen. Dit opent mogelijkheden voor het maken van instanties via reflectie, werken met serializers en het verkrijgen van klasseannotaties tijdens de uitvoering.

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

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

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

// Annotaties verkrijgen
inline fun <reified T> hasAnnotation<A>(): Boolean where A : Annotation =
    T::class.java.isAnnotationPresent(A::class.java)

De wrapper fromJson voor Gson — een klassiek voorbeeld van het gebruik van reified in productie. In plaats van gson.fromJson(json, User::class.java) kan men gson.fromJson(json) schrijven. Dit lijkt een kleine verbetering, maar in een project met honderden serialisatie-aanroepen vermindert reified de boilerplate aanzienlijk en maakt de code schoner.

Beperkingen van reified en alternatieven

reified heeft beperkingen. Ten eerste — werkt alleen binnen inline-functies. Als een functie niet inline kan worden gemaakt (bijvoorbeeld recursief of te groot), is reified niet beschikbaar. Ten tweede — reified kan niet direct worden gebruikt met suspend-functies, alleen via inline wrappers.

Ten derde — reified werkt niet volledig met geparametriseerde typen. Bijvoorbeeld filterByType>() kan een onverwacht resultaat geven, omdat reified voor geparametriseerde typen alleen het ruwe type (List) behoudt, zonder de generic-argumenten te specificeren. Voor volledige controle van geparametriseerde typen is reflectie met TypeToken vereist.

BewerkingMet reifiedZonder reified
value is T✅ Werkt❌ Compilatiefout
T::class✅ Werkt❌ Compilatiefout
List is T⚠️ Alleen raw type❌ Fout
Instantie maken✅ Via reflectie❌ Class nodig
Suspend-functie❌ Alleen via inline wrapper❌ Niet van toepassing

Voor gevallen waarin reified niet beschikbaar is, gebruik dan het patroon met expliciete overdracht van Class of TypeToken uit bibliotheken (bijvoorbeeld Gson TypeToken of Jackson TypeReference). Deze benadering werkt in elke functie, maar vereist boilerplate en is minder handig.

Veelgestelde vragen

Waarom werkt reified alleen met inline-functies?

De compiler vervangt de reified-parameter T door het concrete type tijdens het inlinen van de functiebody. Als de functie niet inline is, heeft de compiler geen plek om het type te substitueren — de aanroep van de generic-functie vindt plaats via uniforme bytecode, waar T is gewist. Inline maakt een aparte kopie van bytecode voor elk type-argument.

Kan men een reified property declareren?

Nee, reified is alleen van toepassing op functieparameters. Voor properties gebruikt men het patroon inline fun met een retourwaarde of expliciete overdracht van Class via de constructor. Extension properties ondersteunen ook geen reified.

Hoe werkt reified met nullable-types?

reified ondersteunt nullable-types: reified T : Any (non-null) en gewoon reified T (kan nullable zijn). Voor nullable-types geeft T::class de klasse voor de non-null versie terug (String::class voor String?). De controle value is T houdt rekening met null: als T = String?, dan is null is T = true.

Heeft reified overhead?

Minimaal. reified gebruikt geen reflectie — de compiler substitueert het concrete type tijdens de inlining-fase. In bytecode is dit een directe verwijzing naar de klasse (ldc + checkcast/invokevirtual). Er is geen overhead in vergelijking met handmatige overdracht van Class — beide varianten genereren dezelfde bytecode.

Kan reified worden gebruikt in Android-ontwikkeling?

Ja, reified wordt actief gebruikt in Android. Bundle.getParcelable(), Intent.getSerializableExtra(), viewModels() uit Android KTX — al deze functies gebruiken reified om expliciete overdracht van Class te vermijden. Volgens gegevens uit Google Android Docs (2025) wordt reified aanbevolen voor generic-API waar het type in runtime nodig is.

Samenvatting

  • reified — modifier van de generic-parameter van een inline-functie, bewaart het type in runtime
  • Type erasure — het standaardmechanisme voor het wissen van typen; reified omzeilt het door inlining
  • is/as — typecontrole en -conversie werken met reified zoals met gewone klassen
  • Klasseverwijzing — T::class en T::class.java zijn beschikbaar voor reflectie en serialisatie
  • Alleen inline — reified is onmogelijk zonder inline-functie vanwege het type-substitutiemechanisme
  • Geparametriseerde typen — reified behoudt geen generic-argumenten (alleen raw type)
  • Toepassing — Gson/Moshi serialisatie, DI-containers, typecontroles in collecties, Android KTX

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook