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.
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.
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.
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.
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.
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.
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.
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
- 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.
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
List all Kotlin tutorials.