В этом случае reified
помогает распространять класс типа, но все еще есть стирание типа.
Чтобы избежать этого, вы можете использовать что-то вроде JavaType
:
inline fun <reified V> String.parseList(): List<V> {
return objectMapper.readValue(this, objectMapper.getTypeFactory()
.constructCollectionType(List::class.java, V::class.java))
}
Обратите внимание, чтобез reified
мы не смогли бы использовать V::class.java
Теперь, чтобы ответить на ваш второй вопрос, как получается, что, хотя val actual
равно List<User>
, вы получаете ClassCastException
- ответ сновастирание типов с некоторым запутыванием типов платформ.
Если вы посмотрите, что возвращает эта функция (это ваша функция без asList()
вызова:
inline fun <reified V> String.parseList() =
objectMapper.readValue(this, Array<V>::class.java)
Вы заметите, что она возвращает Array<???>!
, который является способом Котлина сказать "это что-то из Java, я надеюсь, что это будет работать, но я не могу обещать". Теперь, вызывая toList()
, это расслабляет компилятор, говоря: "да, в конце мы возвращаемТип Kotlin, все будет хорошо ". Но на самом деле это ложное обещание.
То, что вы получите, будет Array<Any>
заполнено LinkedHashMap
, что, конечно, не удастся, когда их приводят к User
основываясь на ложном обещании, которое мы дали компилятору.