What is reified in Kotlin and why is it "magic"?
\nIf you've ever written in Java, you've certainly encountered Type Erasure — the erasure of types at runtime. In Java (and in Kotlin by default), type information inside generics is only available at compile time, and disappears at runtime. This means you cannot write if (value is T) or T::class inside a regular function, because T at runtime is just Object.
But Kotlin went further. The keyword reified allows you to "revive" the type inside an inline function. Thanks to reified, you can do what seemed impossible in Java: check the type, get KClass, create instances, and even work with reflection — all at runtime.
In this article, we'll break down how reified works with real examples you can apply immediately. Let's go!
\n\nThe Problem: Type Erasure in Action
\nImagine: you're writing a function that should check if an object is a string. A naive attempt:
\nfun <T> isString(value: Any): Boolean {\n return value is T // Compilation error!\n}\nThe compiler will give an error: "Cannot check for instance of erased type: T". Why? Because at runtime, the JVM doesn't know what T is. For it, T is just Object.
The same goes for getting the class: T::class inside a regular function won't work either. This is Type Erasure — the main headache for Java developers.
The Solution: reified + inline
\nKotlin offers an elegant way out. To "remember" the type at runtime, you need to make the function inline and mark the type parameter with the keyword reified:
\ninline fun <reified T> isString(value: Any): Boolean {\n return value is T // Now it works!\n}\nNow you can call:
\nprintln(isString<String>("Hello")) // true\nprintln(isString<Int>("Hello")) // false\nHow does it work? When you mark a function as inline, the compiler inlines its code directly at the call site. And reified forces the compiler to substitute the specific type (e.g., String) instead of T in the generated code. As a result, an explicit check value is String appears in the bytecode.
Practical Examples of Using reified
\nLet's look at several real-world scenarios where reified really simplifies life.
\n\n1. Getting the Class at Runtime
\nOne of the most common tasks is to get KClass or Class from a type parameter. Without reified, this is impossible:
inline fun <reified T> getKClass(): KClass<T> = T::class\n\n// Usage:\nval kClass = getKClass<String>()\nprintln(kClass.simpleName) // String\nThis is especially useful when working with libraries that require reflection (e.g., serialization, ORM, DI containers).
\n\n2. Creating an Instance by Type
\nWant to create an object of the required type without passing a constructor? Easy:
\ninline fun <reified T : Any> createInstance(): T {\n return T::class.createInstance()\n}\n\n// Example:\nval instance = createInstance<StringBuilder>()\ninstance.append("Hello, reified!")\nBut be careful: createInstance() only works if the class has a no-argument constructor. Otherwise, you'll get an exception.
3. Filtering by Type in Collections
\nSuppose you have a list of objects of different types, and you want to filter only strings. The Kotlin standard library has filterIsInstance<T>(), but you can easily write your own version:
Blogs
Book Recommendations
Read also
WebSocket in C++: Advanced-Level Real-Time Applications
Property has no initializer in TypeScript: how to fix in 5 minutes
Generics in Go: why they are needed and how to use them
Generics in PHP: Why They Are Needed and How to Use Them for Beginners
Speed Up Python Code: Proven Optimization Techniques