首页 > 解决方案 > 嵌套的具体化参数无法创建 ParameterizedTypeReference

问题描述

我有以下带有 reified 参数的内联函数来概括 http 资源获取:

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>>())
}

我正在构建ParameterizedTypeReference一个typeRef支持功能,如下所示

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

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

请注意,我正在将typeRef<List<N>>N 被具体化的地方从getResources()传递到预期的具体化类型 T ,typeRef()但它似乎无法正确构建其类型。

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

更新:

我已经重构了代码以直接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>>() {})
}

标签: springgenericskotlinkotlin-reified-type-parameters

解决方案


似乎 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>>
}

然后我只是在传递嵌套类型的java类(S::class.java)的getResources()函数中使用它:

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))
}

推荐阅读