Question
I'm trying to understand the purpose of the reified keyword in Kotlin. It seems to allow reflection-like operations on generic types.
However, when I remove it, my code still appears to work fine. In what situations does reified actually make a real difference?
Short Answer
By the end of this page, you will understand what reified means in Kotlin, why it only works with inline functions, and when it is necessary instead of a normal generic type parameter. You will also see the difference between generic type information that is erased at runtime and type information that becomes available through reification.
Concept
In Kotlin, generic type parameters such as T are usually erased at runtime. This is called type erasure.
That means inside a normal generic function, the program often does not know the actual type that was used for T once the code is running.
For example, in a regular function like this:
fun <T> printType(value: T) {
// You cannot reliably use T::class here
}
T is mainly useful at compile time. The compiler checks types for safety, but the runtime usually does not keep that generic type information.
reified changes this behavior for inline functions.
When you write:
inline fun <reified T> example() {
println(T::class)
}
Kotlin replaces the function call with the actual function body at compile time. Because of that, the compiler can substitute the real type argument directly into the generated code.
So instead of treating T as an unknown erased type, the function can act as if the actual type is available at runtime.
This matters when you want to do things like:
Mental Model
Think of a normal generic type T as a label written in pencil on a box.
At compile time, the label helps you organize things correctly. But at runtime, the label gets erased, so the program no longer clearly sees what was written.
A reified type is like turning that pencil label into a printed sticker right when the box is handed over.
Because the function is inline, Kotlin copies the function body directly to the call site and can replace T with the real type, such as String or Int.
So:
- normal generic
T= the runtime often forgets the exact type reified T= the actual type is written into the generated code at the call site
That is why reified is useful when the code needs to inspect or check the type while running.
Syntax and Examples
Basic syntax
reified must be used with an inline function:
inline fun <reified T> showType() {
println(T::class)
}
Call it like this:
showType<String>()
showType<Int>()
Example: checking a type
inline fun <reified T> isOfType(value: Any): Boolean {
return value is T
}
fun main() {
println(isOfType<String>("hello")) // true
println(isOfType<String>(123)) // false
}
Why this is useful
Without reified, this does not work:
Step by Step Execution
Consider this code:
inline fun <reified T> matchesType(value: Any): Boolean {
return value is T
}
fun main() {
val result1 = matchesType<String>("Kotlin")
val result2 = matchesType<String>(42)
println(result1)
println(result2)
}
What happens step by step
- The compiler sees that
matchesTypeis markedinline. - Instead of generating one shared generic function call, Kotlin copies the function body into each call site.
- For
matchesType<String>("Kotlin"),Tis replaced withString. - The generated logic becomes effectively similar to:
val result1 = "Kotlin" is String
- For
matchesType<String>(42), the generated logic becomes effectively similar to:
Real World Use Cases
reified is most useful when a helper function needs to know the concrete type at runtime.
1. JSON parsing helpers
Libraries often need a target type.
inline fun <reified T> parseJson(json: String): T {
// Example idea: a JSON library uses T's type here
throw NotImplementedError("Demo only")
}
This is cleaner than forcing callers to pass T::class every time.
2. Dependency injection or service lookup
inline fun <reified T> resolve(): T {
throw NotImplementedError("Demo only")
}
A container can look up an object by type.
3. Filtering collections by type
Kotlin standard library uses this idea:
val mixed: List<Any> = listOf("a", 1, , )
strings = mixed.filterIsInstance<String>()
println(strings)
Real Codebase Usage
In real Kotlin projects, reified usually appears in small utility functions that make APIs easier to call.
Common patterns
Guard clauses based on type
inline fun <reified T> requireType(value: Any) {
require(value is T) { "Expected ${T::class.simpleName}" }
}
This is useful for validation and defensive programming.
Wrapper functions around libraries
A library may require a Class<T> or KClass<T>. Teams often write a reified wrapper:
fun <T : Any> loadConfig(type: kotlin.reflect.KClass<T>): T {
throw NotImplementedError("Demo only")
}
inline fun <reified T : Any> loadConfig: T {
loadConfig(T::)
}
Common Mistakes
1. Thinking reified is needed for all generics
This is the most common misunderstanding.
Broken idea:
inline fun <reified T> identity(value: T): T {
return value
}
This works, but reified adds no benefit here because the function never uses T at runtime.
Use reified only when you need runtime access to the type.
2. Forgetting that reified requires inline
Broken code:
fun <reified T> printType() {
println(T::class)
}
This will not compile.
Correct version:
inline {
println(T::)
}
Comparisons
| Concept | What it does | Runtime type access | Typical use |
|---|---|---|---|
Normal generic fun <T> | Uses a type parameter for compile-time safety | Usually no | Data processing, collections, reusable functions |
inline fun <reified T> | Makes the concrete type available in inline-generated code | Yes, for many type operations | Type checks, casts, class lookup, wrappers around reflection |
Passing KClass<T> manually | Caller provides the type explicitly | Yes | Constructors, factories, reflection-heavy APIs |
reified vs explicit class parameter
fun <T : Any> create: T {
NotImplementedError()
}
: T {
create(T::)
}
Cheat Sheet
Quick rules
- Generic types in Kotlin are usually erased at runtime.
- Use
reifiedwhen you need the actual typeTwhile the program is running. reifiedonly works on inline functions.- Common uses:
T::classT::class.javavalue is Tvalue as? T
Core syntax
inline fun <reified T> example(value: Any): Boolean {
return value is T
}
Without reified
Pass the type explicitly:
fun <T : Any> example(type: kotlin.reflect.<>) {
println(type.simpleName)
}
FAQ
Why does my Kotlin generic function work without reified?
Because many generic functions only need compile-time type safety, not runtime type inspection. If you are not doing is T, as? T, or T::class, reified may not be needed.
Why does reified require inline in Kotlin?
Because Kotlin makes reified work by copying the function body to each call site and replacing T with the actual type used there.
Can I use reified in a normal class method without inline?
No. A type parameter can only be reified in an inline function.
Is reified the same as reflection?
No. It is a way to preserve access to a generic type argument in inline functions. It can help with reflection-like tasks, but it is not full reflection by itself.
When should I use reified instead of passing Class or ?
Mini Project
Description
Build a small type-filtering utility for a mixed list. This demonstrates exactly why reified is useful: the function needs to keep only items of a requested type at runtime.
Goal
Create a reusable Kotlin function that returns only values of a specific type from a mixed collection.
Requirements
- Create an
inlinefunction with areifiedtype parameter. - Accept a
List<Any>as input. - Return a new list containing only items of type
T. - Demonstrate the function with at least two different target types.
- Print the results clearly.
Keep learning
Related questions
Android AlarmManager Example: Scheduling Tasks with AlarmManager
Learn how to use Android AlarmManager to schedule tasks, set alarms, and handle broadcasts with a simple beginner example.
Can You Extend a Data Class in Kotlin? Inheritance, Limits, and Better Alternatives
Learn why Kotlin data classes cannot be extended, what causes the component function clash, and which alternatives to use instead.
Difference Between List and Array in Kotlin
Learn the difference between List and Array in Kotlin, including mutability, size, APIs, performance, and when to use each one.