Unlocking Kotlin’s Reified Types: How Inline Functions Bring Runtime Type Safety
Discover how Kotlin’s inline functions with reified type parameters let you perform type-safe generics at runtime, boost performance, and simplify API design. Learn the trade‑offs, see a concrete example, and get actionable guidance for your next project.
17 Jan 2026, 02:30 UTC

Why Runtime Type Information Matters in Kotlin
When writing generic code in Kotlin, you often need to know the concrete type at runtime—for example, when deserialising JSON or storing objects in a type‑safe cache. The JVM erases generic type parameters at compile time, so a normal function like fun read(json: String): T cannot inspect T during execution. Kotlin solves this with reified type parameters, but only inside inline functions. This combination gives you compile‑time type safety without the usual runtime overhead.
What Are Inline Functions and Reified Types?
An inline function is a compile‑time transformation: the compiler copies the function body into every call site. Because the generic type is known when the body is inlined, the compiler can replace references to T with the concrete type. A reified type parameter is a generic type that the compiler keeps after inlining, allowing runtime access to that type via T::class or is T checks.
Key points:
- Only functions marked
inlinecan usereifiedtype parameters. - Reification removes the need for explicit
Class<T>arguments. - Because the code is inlined, there is no additional method call overhead.
Practical Use Case: A Generic JSON Factory
Consider a common pattern: converting a JSON string into a data class instance. Without reified types you would write:
inline fun fromJson(json: String, clazz: Class<T>): T = Json.decodeFromString(clazz, json)
And call it like:
val user: User = fromJson(json, User::class.java)
With a reified type parameter the function becomes:
inline fun <reified T> fromJson(json: String): T = Json.decodeFromString<T>(json)
Now you can simply write:
val user: User = fromJson(json)
Behind the scenes, the compiler replaces T with User at the call site, eliminating the need for a Class<T> argument and the associated reflection overhead.
Performance Gains and Bytecode Size
Inlining removes a method call, which saves stack frame allocation and improves cache locality. Reification also eliminates the allocation of a type token (e.g., a Class<T> instance). However, the trade‑off is that the inlined code is duplicated at every call site, which can increase the compiled class file size. In small, frequently called helper functions this is negligible, but for large functions or libraries used across many modules, the bytecode bloat can become noticeable.
To gauge the impact, run javap -c on a class that uses the inline reified function and compare the bytecode size before and after inlining. If the method size grows beyond a few hundred bytes, consider extracting the logic into a non‑inline helper or limiting reified usage to critical paths.
Limitations and Interoperability
- Reified types are not preserved for Java callers. A Java method that calls a Kotlin inline function with a reified parameter will see the generic erased to
Objectunless the Kotlin function is exposed with an explicitClass<T>parameter. - You cannot declare a reified type in a non‑inline function or in a class/extension that is not inlined. Attempting to do so results in a compiler error.
- Because the code is inlined, debugging can be more difficult: stack traces will point to the caller rather than the inlined function.
Actionable Checklist
- Identify small, frequently used generic helpers (e.g., JSON parsing, type‑safe casts) that would benefit from inlining.
- Mark them as
inlineand addreifiedto the type parameter. - Use Kotlin’s
Show Bytecodeorjavap -cto verify that the generic type is replaced with the concrete type in the generated class file. - Measure the compiled class size and runtime performance in a representative test harness.
- If the bytecode size grows significantly or you need Java interop, revert to a non‑inline version that accepts a
Class<T>argument.
Conclusion
Kotlin’s inline functions with reified type parameters provide a powerful tool for writing clean, type‑safe generic code while keeping runtime overhead low. They shine in scenarios where you need to inspect or cast to a generic type without resorting to reflection, such as JSON deserialisation or type‑safe caching. By following the checklist above, you can harness this feature effectively while staying aware of its limitations and impact on bytecode size.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.