reified — ett nyckelord i språket Kotlin som gör det möjligt att få åtkomst till typen av en generic-parameter inuti en inline-funktion under körning. I vanliga generics fungerar type erasure — information om typen raderas i kompileringsfasen, men reified bevarar den. Enligt Kotlin Documentation, 2025 fungerar reified endast inuti inline-funktioner, eftersom kompilatorn ersätter den verkliga typen i inliningsfasen.
Huvudpunkter
reified — är en modifierare av generic-parametern för en inline-funktion som gör typen verklig (reify — “förverkliga”) vid körning. Utan reified är typen T inuti en generic-funktion inte tillgänglig — kompilatorn tillämpar type erasure och raderar all information om typen. reified tvingar kompilatorn att ersätta den konkreta typen vid anropet, vilket gör den tillgänglig via T::class och operatorn is.
Enligt Kotlin Survey by Kodee (2024) hör reified type parameters till de tio mest efterfrågade funktionerna i Kotlin — 52 % av de tillfrågade utvecklarna använder dem, främst för att skriva generic-fabriker, DI-containrar och serialiserare. Reified är särskilt populärt i kombination med Gson, Moshi och Kotlinx Serialization.
Tekniskt sett är mekanismen enkel: vid anrop av en inline-funktion med en reified-parameter känner kompilatorn till den konkreta typen av argumentet (Int, String, User) och ersätter den i stället för T. I bytekod omvandlas reified-parametern till en vanlig Class
Använd reified för att skriva generic-funktioner där typen behövs vid körning — skapa instanser, typkontroller, hämta Class
Type erasure — mekanismen i Java och Kotlin där information om generic-parametrar raderas under kompilering. I bytekod blir List
// ❌ Fel: Kan inte kontrollera instans av raderad typ
fun <T> checkType(value: Any) {
if (value is T) { // type erasure — T är okänd
println("Typen matchar")
}
}
// ✅ Solution: pass Class as parameter
fun <T> checkTypeWithClass(
value: Any,
clazz: Class<T>
) {
if (clazz.isInstance(value)) {
println("Typen matchar")
}
}
I exemplet kompileras inte checkType på grund av type erasure — kompilatorn vet inte vilken typ som ska ersätta T. I checkTypeWithClass löses problemet genom explicit överföring av Class
Modifieraren reified placeras före generic-parametern i en inline-funktion. Funktionen måste vara inline — kompilatorn måste ha möjlighet att ersätta den konkreta typen i inliningsfasen.
inline fun <reified T> isA(value: Any): Boolean {
return value is T
}
fun main() {
println(isA<String>("Hej")) // true
println(isA<Int>("Hej")) // false
}
Under kompilering ersätts anropet isA
Om vi dekompilerar bytekoden för isA
Den vanligaste tillämpningen av reified — typkontroll via operatorn is. I en vanlig generic-funktion kompileras inte value is T. Med reified fungerar det som med en vanlig klass: 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]
Utökningsfunktionen filterByType filtrerar listan och lämnar endast element av den angivna typen. Utan reified skulle man behöva skriva filterByType
Enligt data från Kotlin Coroutines Guide (JetBrains, 2025) används reified typkontroller i launch och async för att skicka korutinens resultattyp, vilket gör att explicit typangivelse kan undvikas i de flesta fall.
Reified ger åtkomst till T::class — en referens till KClass, från vilken Java Class kan erhållas via .java. Detta öppnar möjligheter för att skapa instanser via reflektion, arbeta med serialiserare och hämta klassannoteringar under körning.
inline fun <reified T> createInstance(): T =
T::class.java.getDeclaredConstructor().newInstance()
// Användning
data class User(val name: String = "default")
val user = createInstance<User>()
// Serialisering med Gson
inline fun <reified T> Gson.fromJson(json: String): T =
this.fromJson(json, T::class.java)
// Hämta annoteringar
inline fun <reified T> hasAnnotation<A>(): Boolean where A : Annotation =
T::class.java.isAnnotationPresent(A::class.java)
Wrapper fromJson för Gson — ett klassiskt exempel på användning av reified i produktion. I stället för gson.fromJson(json, User::class.java) kan man skriva gson.fromJson
Reified har begränsningar. För det första — fungerar endast inuti inline-funktioner. Om en funktion inte kan göras inline (till exempel är rekursiv eller för stor), är reified inte tillgänglig. För det andra — reified kan inte användas direkt med suspend-funktioner, endast via inline-wrappers.
För det tredje — reified fungerar inte fullt ut med parametriserade typer. Till exempel kan filterByType>() ge ett oväntat resultat, eftersom reified för parametriserade typer endast bevarar råtypen (List), utan att specificera generic-argumenten. För fullständig kontroll av parametriserade typer krävs reflektion med TypeToken.
| Operation | Med reified | Utan reified |
|---|---|---|
| value is T | ✅ Fungerar | ❌ Kompileringsfel |
| T::class | ✅ Fungerar | ❌ Kompileringsfel |
| List | ⚠️ Endast raw type | ❌ Fel |
| Skapa instans | ✅ Via reflektion | ❌ Kräver Class |
| Suspend-funktion | ❌ Endast via inline-wrapper | ❌ Ej tillämpligt |
För fall där reified inte är tillgänglig, använd mönstret med explicit överföring av Class
Vanliga frågor
Kompilatorn ersätter reified-parametern T med den konkreta typen under inlinering av funktionskroppen. Om funktionen inte är inline har kompilatorn ingen plats att ersätta typen — anropet av generic-funktionen sker via enhetlig bytekod, där T har raderats. Inline skapar en separat kopia av bytekod för varje typ-argument.
Nej, reified är endast tillämpligt på funktionsparametrar. För egenskaper används mönstret inline fun
Reified stöder nullable-typer: reified T : Any (non-null) och helt enkelt reified T (kan vara nullable). För nullable-typer returnerar T::class klassen för non-null-versionen (String::class för String?). Kontrollen value is T tar hänsyn till null: om T = String?, då är null is T = true.
Minimal. Reified använder inte reflektion — kompilatorn ersätter den konkreta typen i inliningsfasen. I bytekod är detta en direkt referens till klassen (ldc + checkcast/invokevirtual). Det finns ingen overhead jämfört med manuell överföring av Class
Ja, reified används aktivt i Android. Bundle.getParcelable
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också