Normally, you can't pass a generic type to a function and access it as if it were a class. This is because of type erasure: generic types are erased at compile time and aren't normally accessible at runtime.
fun <T> deserializeObject(json: String): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(json, T::class.java) //does not compile!
}
To get around this, we can pass the class to the function:
fun <T> deserializeObject(json: String, clazz: KClass<T>): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(json, clazz.java)
}
...
data class Example(val name: String)
val json = """{"name":"example"}"""
deserializeObject(json, Example::class)
With Kotlin, we can do better! With a reified
type, we can tell Kotlin that we want to maintain
access to the type at runtime. Functions that use reified
types must be inline
: the compiler will
inline the function's bytecode everywhere the function is called, with the types specified.
inline fun <reified T> deserializeObject(json: String): T {
val mapper = jacksonObjectMapper()
return mapper.readValue(json, T::class.java)
}
...
data class Example(val name: String)
val json = """{"name":"example"}"""
deserializeObject<Example>(json)