Kotlin Reified Types in Inline Functions
I've noticed that many people haven't ever heard of reified
types or have problems understanding what they are and what they do. Therefore this little post is intended to bring some light into the darkness of Kotlin's reified
types.
Starting situation
fun <T> myGenericFun(c: Class<T>)
In an ordinary generic function like myGenericFun
, you can't access the type T
because it is, like in Java, erased at runtime and thus only available at compile time. Therefore, if you want to use the generic type as a normal Class
in the function body you need to explicitly pass the class as a parameter like the parameter c
in the above example. That's correct and works fine but makes it a bit unsightly for the caller.
Inlined function with reified
to the rescue
If, on the other hand, you use an inline function with a reified
generic type T
, the value of T
can be accessed even at runtime and thus you don't need to pass the Class<T>
additionally. You can work with T
as if it was a normal Class
, e.g. you might want to check whether a variable is an instance of T
, which you can easily do like this: myVar is T
.
An inline
function with reified
type looks like this:
inline fun <reified T> myGenericFun()
Be aware that reified
types can only be used in combination with inline
functions. Such an inline
function makes the compiler copy the function's bytecode to every place where the function is being called (the function is being "inlined"). When you call an inline
function with reified
type, the compiler knows the actual type used as a type argument and modifies the generated bytecode to use the corresponding class directly. Therefore calls like myVar is T
become myVar is String
(if the type argument were String
) in the bytecode and at runtime.
Reified in Action
Let's have a look at an example, where reified
is really helpful. We want to create an extension function for String
called toKotlinObject
, which tries to convert a JSON string to a Kotlin Object, specified by the function's type T
. We can use com.fasterxml.jackson.module.kotlin
for this and the first approach is the following:
First approach without reified type
fun <T> String.toKotlinObject(): T {
val mapper = jacksonObjectMapper()
//does not compile!
return mapper.readValue(this, T::class.java)
}
The readValue
method takes a type that it is supposed to parse the JsonObject
to. If we try to get the Class
of the type parameter T
, the compiler complains: "Cannot use 'T' as reified type parameter. Use a class instead."
Workaround with explicit Class parameter
fun <T: Any> String.toKotlinObject(c: KClass<T>): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, c.java)
}
As a workaround, we pass the Class
of T
explicitly, which can directly be used as an argument to readValue
. This works and is actually a common pattern in Java code for such scenarios. The function can be called like so:
data class MyJsonType(val name: String)
val json = """{"name":"example"}"""
json.toKotlinObject(MyJsonType::class)
The Kotlin way: reified
Using an inline
function with reified
type parameter T
makes it possible to implement our function as follows:
inline fun <reified T: Any> String.toKotlinObject(): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(this, T::class.java)
}
There's no need to pass the Class
of T
additionally, T
can be used as if it was an ordinary class. For the client the code looks like this:
json.toKotlinObject<MyJsonType>()
Important
Inline reified functions are not callable from Java code, whereas normal inline functions are. That's probably the reason why not all type parameters used in inline
functions are reified
by default.
Conclusion
This was just a quick introduction to reified
types. In my opinion, the call to a function with reified
types looks way better because we can make use of the <>
-syntax commonly used whenever generics are relevant. As a result, it's more readable than the Java approach of passing a Class
object as a parameter. More details can be read in this specification document.
If you want to read more about Kotlin's beautiful features I recommend the book Kotlin in Action to you and also like to direct you to my other articles 🙂
Simon is a software engineer with 9+ years of experience developing software on multiple platforms including the JVM and Serverless environments. He currently builds scalable distributed services for a decision automation SaaS platform. Simon is a self-appointed Kotlin enthusiast.
Thank you for this. I have always wanted to understand what this `reified` in kotlin means
[…] Same as in Java, generic types are only available at compile time and erased at runtime. This is good enough for most use cases since generics are used in order to ensure type safety. Sometimes though, it’s good to be able to retrieve the actual information at runtime as well. Fortunately, Kotlin comes with a feature called reified types, which makes it possible to work on generic types at runtime (e.g. perform a type check). The concept of reified types has been explained in this article. […]