Вложенный параметр reified не работает для создания ParameterizedTypeReference - PullRequest
0 голосов
/ 22 октября 2018

У меня есть следующая встроенная функция с уточненным параметром для обобщения получения 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 имеет ParameterizedTypeReference.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>>() {})
}

1 Ответ

0 голосов
/ 22 октября 2018

Кажется, что Kotlin не поддерживает использование reified параметров в качестве универсальных типов.

Чтобы обойти это, я использовал 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 (), передавая класс java вложенного типа (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))
}
...