Reified Keyword in Kotlin Explained: Unlock Type Safety

Reified Keyword in Kotlin: Simplify Your Generic Functions

Kotlin’s reified keyword lets your generic functions know the actual type used at runtime, dodging the common issue of type erasure found in Java and standard Kotlin generics. This means you can check and cast types inside generic functions without extra workarounds.

The Problem: Type Erasure in Generics

Ever written a generic function in Kotlin (or Java) and tried to find out what T actually is inside that function? You probably hit a wall. Normally, when your code compiles, the specific type information for generics (like <String> or <Int>) gets wiped out. This is called type erasure. At runtime, your function just sees a plain Object (or its upper bound), not the specific type you called it with.

This means code like this won’t work:

fun <T> printType(value: T) {
    <em>// Error: Cannot use 'T' as reified type parameter. Use a class instead.</em>
    println("The type is: ${T::class.simpleName}") 
}

Why? Because T doesn’t exist as a specific type at runtime due to erasure. The old way around this was to pass the class type explicitly, which felt a bit clunky:

fun <T: Any> printTypeManual(value: T, type: kotlin.reflect.KClass<T>) {
    println("The type is: ${type.simpleName}") 
}

<em>// Calling it:</em>
printTypeManual("Hello", String::class) <em>// Output: The type is: String</em>

It works, but it’s extra typing we’d rather avoid.

The Solution: inline + reified

Kotlin offers a much cleaner way: combine the inline and reified keywords.

  • inline: This tells the compiler to copy the function’s code directly into the place where it’s called, instead of making an actual function call
  • reified: When used on a type parameter T within an inline function, it tells the compiler not to erase the type information for T. The actual type used at the call site gets baked into the inlined code

Let’s fix our previous example:

inline fun <reified T> printTypeReified(value: T) {
    <em>// Now this works!</em>
    println("The type is: ${T::class.simpleName}") 
}

<em>// Calling it is simpler:</em>
printTypeReified("Hello Kotlin!") <em>// Output: The type is: String</em>
printTypeReified(123)          <em>// Output: The type is: Int</em>

See? No need to pass String::class or Int::class. The compiler handles it because the function is inlined and the type is reified.

Practical Use Cases

Okay, printing the type name is neat, but where does reified really shine?

1. Type Checking and Casting (is and as)

This is a big one. Normally, you can’t do value is T inside a generic function because T is erased. With reified, you can!

Imagine filtering a list containing different object types:

<em>// Assume these classes exist: Apple, Orange, Banana</em>
val mixedFruitBasket = listOf(Apple(), Orange(), Banana(), Orange())

<em>// Generic filter without reified (doesn't work well)</em>
<em>// fun <T> List<Any>.filterType(): List<T> { </em>
<em>//     // Error: Cannot check for instance of erased type: T</em>
<em>//     return this.filter { it is T }.map { it as T } </em>
<em>// }</em>

<em>// With reified:</em>
inline fun <reified T> List<Any>.filterTypeReified(): List<T> {
    val result = mutableListOf<T>()
    for (item in this) {
        if (item is T) { <em>// Type check works!</em>
            result.add(item) <em>// Smart cast often works too, but explicit 'as T' might be needed sometimes</em>
        }
    }
    return result
}

<em>// Usage:</em>
val orangesOnly = mixedFruitBasket.filterTypeReified<Orange>()
println(orangesOnly) <em>// Output: [Orange@..., Orange@...]</em>

<em>// Note: Kotlin's standard library already has filterIsInstance<T>() which does this!</em>
val bananasOnly = mixedFruitBasket.filterIsInstance<Banana>()
println(bananasOnly) <em>// Output: [Banana@...]</em>

reified makes type checks (is T) and safe casts (as? T) possible within generic inline functions

2. Working with APIs Expecting Class Types

Many APIs, especially in Android development (like starting Activities or working with Fragments), require you to pass a Class object (YourActivity::class.java). reified makes creating helper functions for these scenarios much nicer.

import android.content.Context
import android.content.Intent
import android.app.Activity

<em>// Without reified</em>
fun <T : Activity> Context.startActivityManual(activityClass: Class<T>) {
    val intent = Intent(this, activityClass)
    startActivity(intent)
}

<em>// With reified</em>
inline fun <reified T : Activity> Context.startActivityReified() {
    val intent = Intent(this, T::class.java) <em>// Accessing .java works!</em>
    startActivity(intent)
}

<em>// Usage (inside an Activity or Context):</em>
<em>// startActivityManual(MyOtherActivity::class.java) // Old way</em>
startActivityReified<MyOtherActivity>() <em>// Much cleaner!</em>

This pattern is super common for simplifying Android Intent creation, Fragment instantiation, database operations, JSON parsing like with libraries such as Gson or Moshi, and dependency injection frameworks.

Quick Summary & Limitations

  • What it does: reified (used with inline) preserves generic type information at runtime.
  • Why use it: Allows type checks (is T), casts (as T), and accessing class info (T::class.java) inside generic functions.
  • Key Benefit: Reduces boilerplate code, especially when interacting with Java APIs or performing type-specific logic in generics.
  • Limitation: Only works with inline functions. Cannot be used on class properties or non-inline function parameters.

So next time you’re fighting type erasure in your Kotlin generics, remember the inline and reified combo – it might just be the clean solution you need!

The reified keyword is a neat tool in your Kotlin toolbox, especially when you’re wrestling with generic type information at runtime. By pairing it with inline functions, you can write cleaner, more readable, and more powerful generic code, sidestepping the usual limitations of type erasure. Just remember it’s specifically for inline functions!

Want to know more about Kotlin generics in general? Check out this guide on generics in Kotlin. You might also find understanding Kotlin Companion Objects helpful for related concepts.


Saiful Alam Rifan

Mobile Application Developer with over 12 years of experience crafting exceptional digital experiences. I specialize in delivering high-quality, user-friendly mobile applications across diverse domains including EdTech, Ride Sharing, Telemedicine, Blockchain Wallets, and Payment Gateway integration. My approach combines technical expertise with collaborative leadership, working seamlessly with analysts, QA teams, and engineers to create scalable, bug-free solutions that exceed expectations. Let's connect and transform your ideas into remarkable mobile experiences.

Recent Posts

Start Building KMP App with Material Design 3 Expressive – 2025

Introduction: Transform Your Cross-Platform Development with Material Design 3 Are you ready to revolutionize your… Read More

1 month ago

Google I/O 2025: A New Era for KMP and Android, Powered by AI

Alright, fellow developers, let's dive into Google I/O 2025. If you blinked, you might have… Read More

3 months ago

What’s New in Jetpack Compose 1.8: Autofill, Text, Visibility & More (2025)

Jetpack Compose 1.8 rolls out handy features like Autofill integration, slick Text enhancements including auto-sizing… Read More

5 months ago

Android Studio Cloud: Develop Android Apps Anywhere (2025)

Android Studio Cloud: Ditch the Setup, Code Anywhere (Seriously!) Alright, fellow Android devs, gather 'round… Read More

5 months ago

Firebase Studio & Google’s AI Dev Tools Guide

Firebase Studio is a new cloud-based platform for building AI-powered apps, launched at Google Cloud… Read More

5 months ago

Kotlin Multiplatform Future: Trends, Use Cases & Ecosystem Growth

1. Emerging Trends in Kotlin Multiplatform 1.1 Expansion to New Platforms KMP is branching beyond… Read More

5 months ago