Reified in Kotlin — was es ist, Syntax und Verwendung

Autor: IT Sectr Veröffentlicht: 2026-06-21 Lesezeit: 8 Min.

reified ist ein Schlüsselwort in Kotlin, das den Zugriff auf den generischen Parametertyp innerhalb von Inline-Funktionen zur Laufzeit ermöglicht. Bei normalen Generics wird Type Erasure angewendet — die Typinformation wird zur Kompilierzeit gelöscht, aber reified bewahrt sie. Laut Kotlin-Dokumentation, 2025 funktioniert reified nur innerhalb von Inline-Funktionen, da der Compiler den tatsächlichen Typ einsetzt.

Wichtigste Punkte

  • reified — ein Modifikator für generische Parameter, der Typinformationen zur Laufzeit bewahrt
  • Nur Inline — reified arbeitet ausschließlich innerhalb von Inline-Funktionen
  • Type Erasure — der Standardmechanismus von Java/Kotlin, der generische Typen löscht; reified umgeht ihn
  • is-Prüfungen — möglich: if (value is T) statt if (value is String)
  • Instanzerstellung — T::class.java.newInstance() ohne Übergabe von Class<T>

Was ist reified in Kotlin?

reified ist ein Modifikator für einen generischen Parameter einer Inline-Funktion, der den Typ zur Laufzeit real macht (reify — „vergegenständlichen”). Ohne reified ist der Typ T innerhalb einer generischen Funktion nicht zugreifbar — der Compiler wendet Type Erasure an und entfernt alle Typinformationen. reified zwingt den Compiler, den konkreten Typ an der Aufrufstelle einzusetzen, sodass er über T::class und den is-Operator zugänglich wird.

Laut der Kotlin-Umfrage von Kodee (2024) gehören reified Typparameter zu den zehn gefragtesten Kotlin-Features — sie werden von 52 % der befragten Entwickler genutzt, hauptsächlich zum Schreiben generischer Fabriken, DI-Container und Serialisierer. Besonders beliebt ist reified in Kombination mit Gson, Moshi und Kotlinx Serialization.

Technisch ist der Mechanismus einfach: Beim Aufruf einer Inline-Funktion mit reified-Parameter kennt der Compiler den konkreten Argumenttyp (Int, String, User) und setzt ihn für T ein. Im Bytecode wird der reified-Parameter zu einem regulären Class<T>, das als verstecktes Argument übergeben wird.

Verwenden Sie reified zum Schreiben generischer Funktionen, bei denen der Typ zur Laufzeit benötigt wird — Instanzerstellung, Typüberprüfungen, Abrufen von Class<T> für Reflexion oder Serialisierung.

Das Problem der Typlöschung bei Generics

Type Erasure ist ein Mechanismus in Java und Kotlin, bei dem Informationen zu generischen Parametern während der Kompilierung gelöscht werden. Im Bytecode werden List<String> und List<Int> zu einfachem List. Dies wurde aus Kompatibilitätsgründen mit Java 1.4 eingeführt, das keine Generics hatte, schafft aber Einschränkungen bei der Arbeit mit Typen zur Laufzeit.

kotlin
// ❌ Fehler: Kann Instanz des gelöschten Typs nicht prüfen
fun <T> checkType(value: Any) {
    if (value is T) { // Type Erasure — T ist unbekannt
        println("Typ stimmt überein")
    }
}

// ✅ Solution: pass Class as parameter
fun <T> checkTypeWithClass(
    value: Any,
    clazz: Class<T>
) {
    if (clazz.isInstance(value)) {
        println("Typ stimmt überein")
    }
}

Im Beispiel kompiliert checkType aufgrund von Type Erasure nicht — der Compiler weiß nicht, welcher Typ für T eingesetzt werden soll. In checkTypeWithClass wird das Problem durch explizite Übergabe von Class<T> gelöst, was jedoch Boilerplate erfordert: Jeder Aufruf wird von .java oder ::class.java begleitet. reified eliminiert dieses Boilerplate vollständig.

Reified-Syntax und Funktionsweise

Der Modifikator reified wird vor dem generischen Parameter in einer Inline-Funktion platziert. Die Funktion muss inline sein — der Compiler muss in der Lage sein, den konkreten Typ zur Inline-Zeit einzusetzen.

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

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

Während der Kompilierung wird der Aufruf isA<String>(„Hello“) durch die Prüfung value is String ersetzt. Der Aufruf isA<Int>(„Hello“) wird zu value is Int. Der Typ wird wörtlich eingesetzt, was die Verwendung von is, as, ::class und anderen Operationen ermöglicht, die bei Type Erasure nicht verfügbar sind.

Dekompilierung einer reified-Funktion

Wenn Sie den Bytecode von isA<String>(„Hello“) dekompilieren, zeigt IntelliJ IDEA in Java in etwa dieses Ergebnis: String.class.isInstance(value). Statt eines generischen Parameters setzte der Compiler die konkrete java.lang.String.class ein — keine Reflexion mit Typsuche per Name, sondern nur ein direkter Klassenverweis.

Typüberprüfungen mit reified: is und as

Die häufigste Verwendung von reified sind Typüberprüfungen mit dem is-Operator. In einer normalen generischen Funktion kompiliert value is T nicht. Mit reified funktioniert es wie mit einer regulären Klasse: value is String, value is List<Int> (fast — mit Einschränkungen für parametrisierte 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]

Die Erweiterungsfunktion filterByType filtert eine Liste und behält nur Elemente des angegebenen Typs. Ohne reified müssten Sie filterByType<String>(list) mit einem Class<String>-Parameter schreiben. Mit reified liest sich der Aufruf wie eine natürliche Operation auf einer Liste, was die Lesbarkeit von Datenverarbeitungsketten verbessert.

Laut dem Kotlin Coroutines Guide (JetBrains, 2025) werden reified Typüberprüfungen in launch und async verwendet, um den Koroutinen-Ergebnistyp zu übergeben und in den meisten Fällen eine explizite Typangabe zu vermeiden.

Reflexion mit reified: Instanzen erstellen und auf Class zugreifen

reified ermöglicht den Zugriff auf T::class — eine Referenz auf KClass, von der Sie über .java die Java-Klasse erhalten. Dies eröffnet Möglichkeiten zur Instanzerstellung über Reflexion, zur Arbeit mit Serialisierern und zum Abrufen von Klassenannotationen zur Laufzeit.

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

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

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

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

Der fromJson-Wrapper für Gson ist ein klassisches Beispiel für die Verwendung von reified in der Produktion. Statt gson.fromJson(json, User::class.java) können Sie gson.fromJson<User>(json) schreiben. Das mag wie eine kleine Verbesserung erscheinen, aber in einem Projekt mit Hunderten von Serialisierungsaufrufen reduziert reified den Boilerplate erheblich und macht den Code sauberer.

Einschränkungen von reified und Alternativen

reified hat Einschränkungen. Erstens — es funktioniert nur innerhalb von Inline-Funktionen. Wenn eine Funktion nicht inline gemacht werden kann (z. B. rekursiv oder zu groß), ist reified nicht verfügbar. Zweitens — reified kann nicht direkt mit Suspend-Funktionen verwendet werden, sondern nur über Inline-Wrapper.

Drittens — reified funktioniert nicht vollständig mit parametrisierten Typen. Beispielsweise kann filterByType<List<String>>() unerwartete Ergebnisse liefern, da reified bei parametrisierten Typen nur den rohen Typ (List) ohne generische Argumente bewahrt. Für eine vollständige Überprüfung parametrisierter Typen ist Reflexion mit TypeToken erforderlich.

OperationMit reifiedOhne reified
value is T✅ Funktioniert❌ Kompilierfehler
T::class✅ Funktioniert❌ Kompilierfehler
List<String> is T⚠️ Nur roher Typ❌ Fehler
Instanzerstellung✅ Über Reflexion❌ Benötigt Class<T>
Suspend-Funktion❌ Nur über Inline-Wrapper❌ Nicht anwendbar

Für Fälle, in denen reified nicht verfügbar ist, verwenden Sie das Muster mit explizitem Class<T> oder TypeToken aus Bibliotheken (z. B. Gson TypeToken oder Jackson TypeReference). Dieser Ansatz funktioniert in jeder Funktion, erfordert aber Boilerplate und ist weniger bequem.

Häufig gestellte Fragen

Warum funktioniert reified nur mit Inline-Funktionen?

Der Compiler ersetzt den reified-Parameter T während des Inlinings des Funktionskörpers durch den konkreten Typ. Wenn die Funktion nicht inline ist, hat der Compiler keine Stelle, um den Typ einzusetzen — ein generischer Funktionsaufruf erfolgt über einen einzigen Bytecode, in dem T gelöscht ist. Inline erstellt eine separate Bytecode-Kopie für jedes Typargument.

Kann man eine reified-Eigenschaft deklarieren?

Nein, reified ist nur auf Funktionsparameter anwendbar. Für Eigenschaften verwenden Sie das Muster inline fun <reified T> mit einem Rückgabewert oder übergeben Class<T> explizit über einen Konstruktor. Erweiterungseigenschaften unterstützen reified ebenfalls nicht.

Wie funktioniert reified mit nullable-Typen?

reified unterstützt nullable-Typen: reified T : Any (nicht-null) und einfach reified T (kann null sein). Bei nullable-Typen gibt T::class die Klasse für die Nicht-Null-Version zurück (String::class für String?). Die Prüfung value is T berücksichtigt null: wenn T = String?, dann ist null is T = true.

Hat reified einen Overhead?

Minimal. reified verwendet keine Reflexion — der Compiler setzt den konkreten Typ zur Inline-Zeit ein. Im Bytecode ist dies ein direkter Klassenverweis (ldc + checkcast/invokevirtual). Im Vergleich zur manuellen Übergabe von Class<T> gibt es keinen Overhead — beide Ansätze erzeugen identischen Bytecode.

Kann man reified in der Android-Entwicklung verwenden?

Ja, reified wird in Android aktiv eingesetzt. Bundle.getParcelable<T>(), Intent.getSerializableExtra<T>(), viewModels<T>() von Android KTX — all diese Funktionen verwenden reified, um Class<T> nicht explizit übergeben zu müssen. Laut Google Android Docs (2025) wird reified für generische APIs empfohlen, bei denen der Typ zur Laufzeit benötigt wird.

Zusammenfassung

  • reified — ein generischer Parametermodifikator für Inline-Funktionen, der den Typ zur Laufzeit bewahrt
  • Type Erasure — der Standardmechanismus zur Typlöschung; reified umgeht ihn durch Inlining
  • is/as — Typüberprüfungen und -konvertierungen funktionieren mit reified wie bei regulären Klassen
  • Klassenreferenz — T::class und T::class.java sind für Reflexion und Serialisierung verfügbar
  • Nur Inline — reified ist ohne Inline-Funktion aufgrund des Typeinsetzungsmechanismus nicht möglich
  • Parametrisierte Typen — reified bewahrt keine generischen Argumente (nur roher Typ)
  • Anwendungen — Gson/Moshi-Serialisierung, DI-Container, Typüberprüfungen in Sammlungen, Android KTX

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch