Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Kotlin: Reified Type Parameters

DZone's Guide to

Kotlin: Reified Type Parameters

Want to see how Kotlin reifies generic type parameters and what doors that opens up for you? Let's walk through some sample code that uses Jackson.

· Java Zone ·
Free Resource

Get the Edge with a Professional Java IDE. 30-day free trial.

This post walks through a sample that demonstrates Kotlin's ability to cleverly reify generic type parameters.

So consider first a world where Kotlin does not support this feature. If we were using the Jackson library to convert JSON to a Map with String-based keys and Integer-based values, I would use code along these lines:

@Test
fun `sample parameterized retrieval raw object mapper`() {
    val objectMapper = ObjectMapper()
    val map: Map<String, Int> = objectMapper.readValue("""
        | {
        |   "key1": 1,
        |   "key2": 2,
        |   "key3": 3
        | }
        """.trimMargin(), object : TypeReference<Map<String, Int>>() {})

    assertThat(map).isEqualTo(mapOf("key1" to 1, "key2" to 2, "key3" to 3))
}


TypeReference, used above, implements a pattern called a Super type token, which allows the type of a parameterized type to be captured by sub-classing. Note the ugly way we create an anonymous sub-class in Kotlin.

object : TypeReference<Map<String, Int>>() {}


What I would like to do is invoke the ObjectMapper the following way instead:

@Test
fun `sample parameterized retrieval`() {
    val om = ObjectMapper()
    val map: Map<String, Int> = om.readValue("""
        | {
        |   "key1": 1,
        |   "key2": 2,
        |   "key3": 3
        | }
        """.trimMargin())

    assertThat(map).isEqualTo(mapOf("key1" to 1, "key2" to 2, "key3" to 3))
}


The generic type parameter is being inferred based on the type of what is to be returned (the left-hand side).

This can be achieved using an extension function on ObjectMapper, which looks like this:

inline fun <reified T> ObjectMapper.readValue(s: String): T = 
        this.readValue(s, object : TypeReference<T>() {})


The inline function is the heart of the support to be able to reify generic type parameters here — after compilation, the function would be expanded out into any place this function is called, and thus, the second version is exactly same as the first version of the test — but reads far better than before.

Note that Jackson already implements these Kotlin extension functions in the excellent jackson-module-kotlin library.

Get the Java IDE that understands code & makes developing enjoyable. Level up your code with IntelliJ IDEA. Download the free trial.

Topics:
java ,kotlin ,jackson ,type parameters ,reification ,tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}