#kotlin
#kotlin
Вопрос:
В моем решении есть следующие классы
open class State<T : Any> { ... }
class CustomState : State<BigDecimal> { ... }
abstract class FindState<T : State<*>> { ... }
class FindStateImpl<T : State<*>> : FindState<T>() { ... }
FindState
может вызываться следующим образом
val strState = FindStateImpl<State<String>>(...)
val intState = FindStateImpl<State<Int>>(...)
val customState = FindStateImpl<CustomState>(...)
Из FindState
класса, который мне нужен, чтобы иметь возможность получать во время выполнения, типы классов для:
T
вFindState<T : State<*>>
котором будутState
или производные от них.T
вState
Таким образом, для приведенных выше примеров мне нужно было бы получить:
val strState = FindStateImpl<State<String>>(...)
//State::class.java
//String::class.java
val intState = FindStateImpl<State<Int>>(...)
//State::class.java
//Int::class.java
val customState = FindStateImpl<CustomState>(...)
//CustomState::class.java
//BigDecimal::class.java (since string is the underlying type T)
Пока у меня есть что-то вроде этого, но это отвратительно и не работает полностью:
val stateType = javaClass.kotlin.supertypes[0].arguments[0].type?.jvmErasure?.javaObjectType
Возможно ли получить эти типы во время выполнения?
Ответ №1:
Предоставленный вами код просто не содержит требуемой информации о типе, поскольку она будет удалена. Доступны только подтипы, которые определяют определенный тип как часть супертипа.
С помощью kotlin есть два способа получения информации о типе:
- Используйте шаблон, подобный Guava
TypeToken
, и убедитесь, что вы предоставляете анонимный объект, содержащий необходимую информацию о типе. Это заставит код отражения работать. - Используйте овеществленный метод и
typeOf<T>()
метод для встраиванияKType
во время компиляции:
inline fun <reified T : Any, CS : State<T>> FindStateEmbedType(state: CS): FindState<CS> {
val contentType = typeOf<T>();
// Do what you need to do with T, perhaps embed in a wrapper FindState type
return FindStateImplWithType(state, contentType)
}
Комментарии:
1. Есть отличная информация о том, почему у нас есть дженерики в этой форме на JVM cr.openjdk.java.net /~briangoetz/valhalla/erasure.html
2. @szymon_prz Жаль, что на этой странице нет раздела комментариев… Даже если вы принимаете все обоснования решений, принятых почти два десятилетия назад (и некоторые из них действительно имеют большой смысл), это не обязательно оправдывает то, что было сделано с тех пор , чтобы уменьшить часть этой боли (т. Е.: Ничего).
3. @gidds да, мы знаем, что на данный момент эта тема осталась позади, и у нас нет никаких других улучшений, но мы получили много других улучшений в других областях, потому что следующие улучшения в дженериках не так нужны нам и требуются сообществу и корпорациям, как другие части JVM или Java, иЯ уверен, что вы также довольны некоторыми улучшениями, сделанными после дженериков 🙂