Reified v Kotlinu — co to je, syntaxe a použití

Autor: IT Sectr Publikováno: 2026-06-21 Doba čtení: 8 min

reified — klíčové slovo v jazyce Kotlin, které umožňuje přístup k typu generic parametru uvnitř inline-funkce během běhu programu. U běžných generics funguje type erasure — informace o typu se maže ve fázi kompilace, ale reified ji uchovává. Podle Kotlin Documentation, 2025, reified funguje pouze uvnitř inline-funkcí, protože kompilátor dosazuje skutečný typ ve fázi vkládání.

Hlavní body

  • reified — modifikátor generic parametru, který uchovává informaci o typu za běhu
  • Inline only — reified funguje výhradně uvnitř inline-funkcí
  • Type erasure — standardní mechanismus Java/Kotlin, který maže generic typy; reified ho obchází
  • Kontroly is — možné: if (value is T) místo if (value is String)
  • Vytváření instancí — vytvoření T::class.java.newInstance() bez předávání Class

Co je reified v Kotlinu?

reified — je modifikátor generic parametru inline-funkce, který činí typ skutečným (reify — “zpřítomnit”) za běhu. Bez reified není typ T uvnitř generic funkce přístupný — kompilátor aplikuje type erasure, čímž maže všechny informace o typu. reified nutí kompilátor dosadit konkrétní typ v místě volání, čímž ho zpřístupňuje přes T::class a operátor is.

Podle Kotlin Survey by Kodee (2024) patří reified type parameters mezi deset nejžádanějších funkcí Kotlinu — používá je 52 % dotázaných vývojářů, především pro psaní generic továren, DI kontejnerů a serializátorů. Reified je obzvláště populární v kombinaci s Gson, Moshi a Kotlinx Serialization.

Technicky je mechanismus jednoduchý: při volání inline-funkce s reified parametrem kompilátor zná konkrétní typ argumentu (Int, String, User) a dosazuje ho místo T. V bajtkódu se reified parametr mění na obyčejný Class, předávaný jako skrytý argument.

Používejte reified pro psaní generic funkcí, kde je typ vyžadován za běhu — vytváření instancí, kontroly typu, získání Class pro reflexi nebo serializaci.

Problém type erasure v generics

Type erasure — mechanismus Javy a Kotlinu, při kterém se informace o generic parametrech maže během kompilace. V bajtkódu se List a List stávají prostě List. Toto bylo provedeno kvůli zpětné kompatibilitě s Java 1.4, kde generics neexistovala, ale vytváří omezení při práci s typy za běhu.

kotlin
// ❌ Chyba: Nelze zkontrolovat instanci vymazaného typu
fun <T> checkType(value: Any) {
    if (value is T) { // type erasure — T je neznámý
        println("Typ se shoduje")
    }
}

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

V příkladu se checkType nekompiluje kvůli type erasure — kompilátor neví, jaký typ dosadit místo T. V checkTypeWithClass je problém vyřešen explicitním předáním Class, ale to vyžaduje boilerplate: každé volání je doprovázeno .java nebo ::class.java. Reified tento boilerplate zcela eliminuje.

Syntaxe reified a mechanismus fungování

Modifikátor reified se umísťuje před generic parametr v inline-funkci. Funkce musí být povinně inline — kompilátor musí mít možnost dosadit konkrétní typ ve fázi vkládání.

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

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

Během kompilace je volání isA("Hello") nahrazeno kontrolou value is String. Volání isA("Hello") — kontrolou value is Int. Typ je dosazen doslovně, což umožňuje použití is, as, ::class a dalších operací nedostupných při type erasure.

Dekompilace reified funkce

Pokud dekompilujeme bajtkód isA("Hello"), IntelliJ IDEA zobrazí přibližně následující výsledek v Javě: String.class.isInstance(value). Místo generic parametru kompilátor dosadil konkrétní java.lang.String.class — žádná reflexe s vyhledáváním typu podle názvu, pouze přímý odkaz na třídu.

Kontroly typů s reified: is a as

Nejčastější použití reified — kontrola typu prostřednictvím operátoru is. V běžné generic funkci se value is T nekompiluje. S reified to funguje jako s běžnou třídou: value is String, value is List (téměř — s ohledem na omezení reified pro parametrizované typy).

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]

Rozšiřující funkce filterByType filtruje seznam a ponechává pouze prvky určeného typu. Bez reified by se muselo psát filterByType(list) s parametrem Class. S reified se volání čte jako přirozená operace nad seznamem, což zlepšuje čitelnost řetězců zpracování dat.

Podle údajů Kotlin Coroutines Guide (JetBrains, 2025) se reified kontroly typů používají v launch a async pro předávání typu výsledku korutiny, což umožňuje vyhnout se explicitnímu určení typu ve většině případů.

Reflexe s reified: vytváření instancí a přístup k Class

reified poskytuje přístup k T::class — odkazu na KClass, ze kterého lze získat Java Class pomocí .java. To otevírá možnosti pro vytváření instancí pomocí reflexe, práci se serializátory a získávání anotací třídy za běhu.

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

// Použití
data class User(val name: String = "default")
val user = createInstance<User>()

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

// Získání anotací
inline fun <reified T> hasAnnotation<A>(): Boolean where A : Annotation =
    T::class.java.isAnnotationPresent(A::class.java)

Obálka fromJson pro Gson — klasický příklad použití reified v produkci. Místo gson.fromJson(json, User::class.java) lze psát gson.fromJson(json). Zdá se to jako malé vylepšení, ale v projektu se stovkami volání serializace reified výrazně snižuje boilerplate a činí kód čistším.

Omezení reified a alternativy

Reified má omezení. Zaprvé — funguje pouze uvnitř inline-funkcí. Pokud funkci nelze učinit inline (například je rekurzivní nebo příliš velká), reified není k dispozici. Zadruhé — reified nelze použít přímo s suspend-funkcemi, pouze prostřednictvím inline obálek.

Zatřetí — reified nefunguje plně s parametrizovanými typy. Například filterByType>() může dát neočekávaný výsledek, protože pro parametrizované typy reified uchovává pouze surový typ (List), bez určení generic argumentů. Pro úplnou kontrolu parametrizovaných typů je vyžadována reflexe s TypeToken.

OperaceS reifiedBez reified
value is T✅ Funguje❌ Chyba kompilace
T::class✅ Funguje❌ Chyba kompilace
List is T⚠️ Pouze raw type❌ Chyba
Vytvoření instance✅ Přes reflexi❌ Vyžaduje Class
Suspend funkce❌ Pouze přes inline obálku❌ Nelze aplikovat

Pro případy, kdy reified není k dispozici, použijte vzor s explicitním předáním Class nebo TypeToken z knihoven (například Gson TypeToken nebo Jackson TypeReference). Tento přístup funguje v libovolných funkcích, ale vyžaduje boilerplate a je méně pohodlný.

Často kladené otázky

Proč reified funguje pouze s inline-funkcemi?

Kompilátor nahrazuje reified parametr T konkrétním typem během vkládání těla funkce. Pokud funkce není inline, kompilátor nemá místo, kam typ dosadit — volání generic funkce probíhá prostřednictvím jednotného bajtkódu, kde je T vymazáno. Inline vytváří samostatnou kopii bajtkódu pro každý typ-argument.

Lze deklarovat reified property?

Ne, reified je použitelné pouze pro parametry funkcí. Pro vlastnosti se používá vzor inline fun s návratovou hodnotou nebo explicitní předání Class přes konstruktor. Extension properties také nepodporují reified.

Jak reified funguje s nullable typy?

reified podporuje nullable typy: reified T : Any (non-null) a prostě reified T (může být nullable). Pro nullable typy vrací T::class třídu pro non-null verzi (String::class pro String?). Kontrola value is T bere v úvahu null: pokud T = String?, pak null is T = true.

Má reified režii?

Minimální. reified nepoužívá reflexi — kompilátor dosazuje konkrétní typ ve fázi vkládání. V bajtkódu je to přímý odkaz na třídu (ldc + checkcast/invokevirtual). Ve srovnání s ručním předáváním Class není žádná režie — obě varianty generují stejný bajtkód.

Lze reified použít ve vývoji pro Android?

Ano, reified se aktivně používá v Androidu. Bundle.getParcelable(), Intent.getSerializableExtra(), viewModels() z Android KTX — všechny tyto funkce používají reified k vyhnutí se explicitnímu předávání Class. Podle údajů Google Android Docs (2025) se reified doporučuje pro generic API, kde je typ vyžadován za běhu.

Shrnutí

  • reified — modifikátor generic parametru inline-funkce, uchovává typ za běhu
  • Type erasure — standardní mechanismus mazání typů; reified ho obchází vkládáním
  • is/as — kontrola a převod typů funguje s reified jako s běžnými třídami
  • Odkaz na třídu — T::class a T::class.java jsou k dispozici pro reflexi a serializaci
  • Pouze inline — reified není možné bez inline-funkce kvůli mechanismu dosazování typu
  • Parametrizované typy — reified neuchovává generic argumenty (pouze raw type)
  • Použití — serializace Gson/Moshi, DI kontejnery, kontroly typů v kolekcích, Android KTX

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také