ZetCode

Kotlin reified Keyword

last modified April 19, 2025

Kotlin's reified keyword solves Java's type erasure limitation in generic functions. It preserves type information at runtime when used with inline functions. This tutorial explores reified in depth with practical examples.

Basic Definitions

The reified keyword in Kotlin is used with type parameters of inline functions. It makes the type information available at runtime, bypassing JVM's type erasure. This enables type checks and casts that would otherwise be impossible with generics.

Simple reified Function

This basic example shows how to create a function with a reified type parameter. The function can check the actual type at runtime.

SimpleReified.kt
package com.zetcode

inline fun <reified T> checkType(obj: Any) {
    if (obj is T) {
        println("Object is of type ${T::class.simpleName}")
    } else {
        println("Object is NOT of type ${T::class.simpleName}")
    }
}

fun main() {
    checkType<String>("Kotlin")  // Output: Object is of type String
    checkType<Int>("123")       // Output: Object is NOT of type Int
}

The checkType function uses a reified type parameter T. It can perform an is check against T and access T's class information. This wouldn't be possible without reified.

Generic Type Checking

Reified parameters allow runtime type checking in generic functions. This example demonstrates type-safe filtering of collections.

TypeCheck.kt
package com.zetcode

inline fun <reified T> filterByType(list: List<Any>): List<T> {
    return list.filter { it is T }.map { it as T }
}

fun main() {
    val mixedList = listOf(1, "Two", 3, "Four", 5.0)
    val strings = filterByType<String>(mixedList)
    
    println(strings) // Output: [Two, Four]
}

The filterByType function filters a list, keeping only elements of type T. The reified parameter enables both the type check and safe cast. This provides type-safe collection operations.

Creating Instances of Generic Types

With reified types, you can create new instances of generic types at runtime. This example shows how to implement a generic factory function.

InstanceCreation.kt
package com.zetcode

inline fun <reified T : Any> createInstance(): T {
    return T::class.constructors.first().call()
}

class Person(val name: String = "Unknown")

fun main() {
    val person = createInstance<Person>()
    println(person.name) // Output: Unknown
}

The createInstance function creates a new instance of type T using reflection. The reified parameter provides access to T's class object. Note that the class must have a parameterless constructor.

JSON Parsing with reified

Reified types are particularly useful for JSON parsing. This example shows a type-safe JSON deserializer.

JsonParser.kt
package com.zetcode

import com.google.gson.Gson

inline fun <reified T> fromJson(json: String): T {
    return Gson().fromJson(json, T::class.java)
}

data class User(val name: String, val age: Int)

fun main() {
    val json = """{"name":"Alice","age":30}"""
    val user = fromJson<User>(json)
    
    println(user) // Output: User(name=Alice, age=30)
}

The fromJson function uses Gson to deserialize JSON into a specified type. The reified parameter provides the Class object needed by Gson. This creates a type-safe JSON parsing utility.

Dependency Injection with reified

Reified types simplify dependency injection by eliminating the need to pass Class objects. This example demonstrates a simple DI container.

DependencyInjection.kt
package com.zetcode

class ServiceLocator {
    private val services = mutableMapOf<Class<*>, Any>()
    
    fun <T : Any> register(service: T) {
        services[service::class.java] = service
    }
    
    inline fun <reified T : Any> resolve(): T {
        return services[T::class.java] as T
    }
}

interface Logger {
    fun log(message: String)
}

class ConsoleLogger : Logger {
    override fun log(message: String) = println(message)
}

fun main() {
    val locator = ServiceLocator()
    locator.register(ConsoleLogger())
    
    val logger = locator.resolve<Logger>()
    logger.log("Hello DI!") // Output: Hello DI!
}

The resolve function uses a reified type parameter to look up services. This eliminates the need to pass Class objects while maintaining type safety. The API becomes cleaner and more intuitive.

Android Intent Extensions

In Android development, reified types simplify intent handling. This example shows a type-safe way to start activities.

AndroidIntent.kt
package com.zetcode

import android.content.Context
import android.content.Intent

inline fun <reified T : Any> Context.startActivity() {
    startActivity(Intent(this, T::class.java))
}

// Example Activity class
class MainActivity : AppCompatActivity()

// Usage in another Activity:
// startActivity<MainActivity>()

The startActivity extension function uses a reified type parameter to create an Intent. This replaces the verbose Intent(this, MainActivity::class.java) pattern. The code becomes more concise and type-safe.

Type-Safe Adapter Pattern

Reified types enable type-safe adapter implementations. This example shows a generic adapter for different data types.

AdapterPattern.kt
package com.zetcode

interface Adapter<T> {
    fun adapt(data: String): T
}

inline fun <reified T> getAdapter(): Adapter<T> {
    return when (T::class) {
        Int::class -> object : Adapter<Int> {
            override fun adapt(data: String) = data.toInt()
        }
        String::class -> object : Adapter<String> {
            override fun adapt(data: String) = data
        }
        else -> throw IllegalArgumentException("No adapter for ${T::class}")
    }
}

fun main() {
    val intAdapter = getAdapter<Int>()
    println(intAdapter.adapt("123")) // Output: 123
    
    val stringAdapter = getAdapter<String>()
    println(stringAdapter.adapt("Hello")) // Output: Hello
}

The getAdapter function returns an appropriate adapter based on the reified type parameter. This creates a type-safe factory pattern without requiring explicit type tokens. The adapters are resolved at compile time.

Best Practices for reified

Source

Kotlin reified Type Parameters Documentation

This tutorial covered Kotlin's reified keyword in depth, showing how it solves type erasure problems. We explored practical examples including JSON parsing, dependency injection, and Android development. Proper use of reified types can make your generic code more type-safe and expressive.

Author

My name is Jan Bodnar, and I am a passionate programmer with many years of programming experience. I have been writing programming articles since 2007. So far, I have written over 1400 articles and 8 e-books. I have over eight years of experience in teaching programming.

List all Kotlin tutorials.