Reified i Kotlin — vad det är, syntax och tillämpning

Författare: IT Sectr Publicerad: 2026-06-21 Lästid: 8 min

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 — modifierare av generic-parametern som bevarar information om typen vid körning
  • Inline only — reified fungerar uteslutande inuti inline-funktioner
  • Type erasure — standardmekanismen i Java/Kotlin som raderar generic-typer; reified kringgår den
  • is-kontroller — möjliga: if (value is T) istället för if (value is String)
  • Skapa instanser — skapa T::class.java.newInstance() utan att skicka Class

Vad är reified i Kotlin?

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, som skickas som ett dolt argument.

Använd reified för att skriva generic-funktioner där typen behövs vid körning — skapa instanser, typkontroller, hämta Class för reflektion eller serialisering.

Problemet med type erasure i generics

Type erasure — mekanismen i Java och Kotlin där information om generic-parametrar raderas under kompilering. I bytekod blir List och List helt enkelt List. Detta gjordes för bakåtkompatibilitet med Java 1.4, där generics inte fanns, men skapar begränsningar när man arbetar med typer vid körning.

kotlin
// ❌ 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, men detta kräver boilerplate: varje anrop åtföljs av .java eller ::class.java. Reified eliminerar helt denna boilerplate.

Syntax för reified och funktionsmekanism

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.

kotlin
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("Hello") med kontrollen value is String. Anropet isA("Hello") — med value is Int. Typen ersätts bokstavligen, vilket möjliggör användning av is, as, ::class och andra operationer som inte är tillgängliga vid type erasure.

Dekompilering av reified-funktion

Om vi dekompilerar bytekoden för isA("Hello") visar IntelliJ IDEA ungefär följande resultat i Java: String.class.isInstance(value). I stället för generic-parametern har kompilatorn ersatt konkret java.lang.String.class — ingen reflektion med sökning av typ efter namn, bara en direkt referens till klassen.

Typkontroller med reified: is och as

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 (nästan — med hänsyn till reifieds begränsningar för parametriserade typer).

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]

Utökningsfunktionen filterByType filtrerar listan och lämnar endast element av den angivna typen. Utan reified skulle man behöva skriva filterByType(list) med parametern Class. Med reified läses anropet som en naturlig operation på listan, vilket förbättrar läsbarheten av databehandlingskedjor.

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.

Reflektion med reified: skapa instanser och åtkomst till Class

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.

kotlin
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(json). Detta verkar vara en liten förbättring, men i ett projekt med hundratals serialiseringsanrop minskar reified boilerplate avsevärt och gör koden renare.

Begränsningar för reified och alternativ

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.

OperationMed reifiedUtan reified
value is T✅ Fungerar❌ Kompileringsfel
T::class✅ Fungerar❌ Kompileringsfel
List is T⚠️ 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 eller TypeToken från bibliotek (till exempel Gson TypeToken eller Jackson TypeReference). Detta tillvägagångssätt fungerar i alla funktioner, men kräver boilerplate och är mindre bekvämt.

Vanliga frågor

Varför fungerar reified endast med inline-funktioner?

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.

Kan man deklarera en reified property?

Nej, reified är endast tillämpligt på funktionsparametrar. För egenskaper används mönstret inline fun med returvärde eller explicit överföring av Class via konstruktorn. Extension properties stöder inte heller reified.

Hur fungerar reified med nullable-typer?

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.

Har reified overhead?

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 — båda varianterna genererar samma bytekod.

Kan reified användas i Android-utveckling?

Ja, reified används aktivt i Android. Bundle.getParcelable(), Intent.getSerializableExtra(), viewModels() från Android KTX — alla dessa funktioner använder reified för att undvika explicit överföring av Class. Enligt data från Google Android Docs (2025) rekommenderas reified för generic-API där typen behövs vid körning.

Sammanfattning

  • reified — modifierare av generic-parametern i inline-funktion, bevarar typen vid körning
  • Type erasure — standardmekanismen för radering av typer; reified kringgår den genom inlining
  • is/as — typkontroll och konvertering fungerar med reified som med vanliga klasser
  • Klassreferens — T::class och T::class.java är tillgängliga för reflektion och serialisering
  • Endast inline — reified är omöjligt utan inline-funktion på grund av typerättningsmekanismen
  • Parametriserade typer — reified bevarar inte generic-argument (endast raw type)
  • Tillämpning — Gson/Moshi-serialisering, DI-containrar, typkontroller i samlingar, Android KTX

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.

Diskutera projektet

Läs också