嵌套化参数无法创建ParameterizedTypeReference

时间:2018-10-22 08:25:16

标签: spring generics kotlin kotlin-reified-type-parameters

我具有以下带有嵌入式参数的内联函数,用于泛化http资源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>>())
}

我正在使用hereParameterizedTypeReference支持功能构建typeRef

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

在调用getResources<Employee>()时,构建的ParameterizedTypeReference包含ParameterizedTypeReference.type.actualTypeArguments而不是java.util.List<? extends N>的{​​{1}}。

请注意,我正在将java.util.List<Employee>传递的typeRef<List<N>>getResources()传递到typeRef()期望的确定类型T,但似乎无法建立其类型正确地

为什么这不起作用?有什么解决方法吗?

更新:

我已经重构了代码,以在第一个内联函数中直接构建ParameterizedTypeReference,但我仍将其作为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>>() {})
}

1 个答案:

答案 0 :(得分:0)

Kotlin似乎不支持将经过修饰的参数用作泛型类型。

要解决此问题,我使用了Guava来生成Type对象并手动构建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>>
}

然后,我只需在getResources()函数中使用它,即可传递嵌套类型(S :: class.java)的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))
}