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 — 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
Gebruik reified voor het schrijven van generic-functies waarbij het type in runtime nodig is — instanties maken, typecontroles, Class
Type erasure — het mechanisme van Java en Kotlin waarbij informatie over generic-parameters wordt gewist tijdens de compilatie. In bytecode worden List
// ❌ 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
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.
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
Als we de bytecode van isA
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
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
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.
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.
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
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.
| Bewerking | Met reified | Zonder reified |
|---|---|---|
| value is T | ✅ Werkt | ❌ Compilatiefout |
| T::class | ✅ Werkt | ❌ Compilatiefout |
| List | ⚠️ Alleen raw type | ❌ Fout |
| Instantie maken | ✅ Via reflectie | ❌ Class |
| 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
Veelgestelde vragen
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.
Nee, reified is alleen van toepassing op functieparameters. Voor properties gebruikt men het patroon inline fun
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.
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
Ja, reified wordt actief gebruikt in Android. Bundle.getParcelable
Samenvatting
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.
Lees ook