3

I have the following inline function with a reified parameter to generalize an http resource get:

inline fun <reified N> getResources(): ResponseEntity<List<N>> {
    val httpEntity = HttpEntity(null, httpHeaders)
    val resourceStr = getResourceString<N>()
    return rest.exchange(testContext.baseUrl + "/api/v1/$resourceStr", HttpMethod.GET,
            httpEntity, typeRef<List<N>>())
}

And I am building the ParameterizedTypeReference with a typeRef support function as answered here:

inline fun <reified T : Any> typeRef(): ParameterizedTypeReference<T>{
    return object : ParameterizedTypeReference<T>() {}
} 

When calling getResources<Employee>(), the ParameterizedTypeReference which is built has ParameterizedTypeReference.type.actualTypeArguments containing java.util.List<? extends N> instead of java.util.List<Employee>.

Notice that I am passing typeRef<List<N>>, where N is reified, from getResources() to the reified type T expected by typeRef() but it doesn't seem to be able to build its type properly.

Why isn't this working? Any work around?

UPDATE:

I've refactored the code to directly build the ParameterizedTypeReferencein the first inline function but I'm still getting it as java.util.List<? extends N>.

private inline fun <reified N> getResources(): ResponseEntity<List<N>> {
    val httpEntity = HttpEntity(null, httpHeaders)
    val resourceStr = getResourceString<N>()
    return rest.exchange(testContext.baseUrl + "/api/v1/$resourceStr", HttpMethod.GET,
            httpEntity, object : ParameterizedTypeReference<List<N>>() {})
}
codependent
  • 23,193
  • 31
  • 166
  • 308

1 Answers1

0

It seems Kotlin doesn't support using reified parameters as generic types.

To work around this I have used Guava to generate a Type object and manually build the ParameterizedTypeReference:

private fun <T : Any> listTypeRef(clazz: Class<T>): ParameterizedTypeReference<List<T>> {
    val type = TypeToken.of(clazz).type
    val make = ParameterizedTypeImpl.make(List::class.java, arrayOf(type), null)
    return ParameterizedTypeReference.forType<T>(make) as ParameterizedTypeReference<List<T>>
}

Then I just use it in the getResources() function passing the java class of the nested type (S::class.java):

inline fun <reified S : Any> getResources(): ResponseEntity<List<S>> {
    val httpEntity = HttpEntity(null, httpHeaders)
    val resourceStr = getResourceString<S>(null)
    return rest.exchange(testContext.baseUrl + "/api/v1/$resourceStr", HttpMethod.GET,
            httpEntity, listTypeRef(S::class.java))
}
codependent
  • 23,193
  • 31
  • 166
  • 308