Why we need reified keyword in Kotlin
In Kotlin, the reified
keyword is used with inline functions to retain the type information at runtime. Normally, due to type erasure in Kotlin and Java, the type information of generic classes is not available at runtime. The reified
keyword solves this by embedding the type information into the bytecode of inline functions.
This is especially useful when working with libraries like Gson, where you need to deserialize JSON into an object of a specific type. Gson requires the type information to parse the JSON correctly, but type erasure makes it unavailable.
Why Do We Need reified
?
Consider the following example where we use Gson to parse JSON into an object:
val json = """{ "name": "John", "age": 30 }"""
// Deserializing JSON without reified
val person = Gson().fromJson(json, Person::class.java)
Here, the type Person
is explicitly provided using Person::class.java
.
If you try to create a generic function to deserialize any type:
fun <T> fromJson(json: String): T {
return Gson().fromJson(json, T::class.java) // ERROR: Cannot use 'T::class'
}
This won’t work because type T
is erased at runtime. You cannot use T::class
or T::class.java
directly without passing the type information explicitly.
Solution with reified
The reified
keyword allows you to retain the type information for T
at runtime in inline functions. Here’s how it works:
inline fun <reified T> fromJson(json: String): T {
return Gson().fromJson(json, T::class.java)
}
Now you can call the function without manually passing the type:
val json = """{ "name": "John", "age": 30 }"""
val person: Person = fromJson(json) // Works without T::class.java
println(person) // Output: Person(name=John, age=30)
How It Works
-
Inline Function:
- The function is marked with
inline
, meaning the compiler inlines the function’s body where it’s called. - This allows the compiler to replace
T
with the actual type.
- The function is marked with
-
Reified Keyword:
- The type
T
becomes available at runtime, allowing operations likeT::class.java
.
- The type
Example: Gson and a Generic API Response
Imagine you’re parsing an API response where the JSON format varies for different data types. Using reified
helps simplify this:
JSON String:
{ "data": { "name": "Alice", "age": 25 } }
Kotlin Code:
data class ApiResponse<T>(val data: T)
data class Person(val name: String, val age: Int)
inline fun <reified T> parseApiResponse(json: String): ApiResponse<T> {
val type = object : TypeToken<ApiResponse<T>>() {}.type
return Gson().fromJson(json, type)
} // Usage val json = """{ "data": { "name": "Alice", "age": 25 } }"""
val response: ApiResponse<Person> = parseApiResponse(json) println(response.data) // Output: Person(name=Alice, age=25)`
Advantages of reified
- Simplifies Generic Code:
- No need to pass
Class<T>
orType
manually.
- No need to pass
- Type Safety:
- Retains type information at runtime, preventing casting issues.
- Readability:
- Cleaner code, especially when dealing with complex generics.
Limitations
- Only works with inline functions.
- Cannot be used in regular functions due to type erasure.
Summary
The reified
keyword is essential in Kotlin for retaining type information at runtime in generic code. It shines when used with libraries like Gson, enabling seamless JSON deserialization without additional boilerplate or manual type specification.