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 — 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
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
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
// ❌ 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
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í.
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
Pokud dekompilujeme bajtkód isA
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
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
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ů.
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.
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
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.
| Operace | S reified | Bez reified |
|---|---|---|
| value is T | ✅ Funguje | ❌ Chyba kompilace |
| T::class | ✅ Funguje | ❌ Chyba kompilace |
| List | ⚠️ 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
Často kladené otázky
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.
Ne, reified je použitelné pouze pro parametry funkcí. Pro vlastnosti se používá vzor inline fun
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.
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
Ano, reified se aktivně používá v Androidu. Bundle.getParcelable
Shrnutí
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í.
Přečtěte si také