Kotlin reified keyword tutorial shows how to preserve type information at runtime. Learn about reified type parameters with examples.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Use with inline functions: reified only works with inline functions as the type information is preserved at compile time. Limit scope: Only use reified when you truly need runtime type information to avoid unnecessary function inlining. Combine with generics: reified shines when working with generic types that would otherwise suffer from type erasure. Consider performance: Inlining large functions with reified types may increase code size. Use for type-safe APIs: reified enables cleaner, type-safe APIs for JSON parsing, DI, and other patterns.
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.
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.