kotlin - 获取具体化泛型类型的具体化类型参数kclass

标签 kotlin generics reflection

给定具体化类型参数 T ,如果该类型是 List ,如何获取列表的项目类型?

我尝试使用 T : Any 重载具体化方法和T : List还有TItem : Any, TList: List<TItem>但由于重载冲突,因此无法编译。

编译失败,重载冲突

inline fun <reified T> getRequiredVariable(variableName: String) =
  // ... implementation

inline fun <reified TItem, reified TList : List> getRequiredVariable(variableName: String) =
  // ... implementation

解决方法尝试失败

inline fun <reified T : Any> getRequiredVariable(variableName: String) =
    if (T::class.isSubclassOf(List::class)) {
        val tKClass = T::class
        val itemType = tKClass.typeParameters[0] // Won't work, even though T is reified, the type parameter apparently is not
        val itemClassifier = itemType.createType().classifier
        val itemKClass = itemClassifier as KClass<*> // Fails, KTypeParamaterImpl is not KClass<*>
        getRequiredListVariable(variableName, itemKClass) as? T
    } else {
        getRequiredVariable(variableName, T::class)
    }

最佳答案

这里的问题是您想要访问类型参数,但是 KClass/Class抽象仅提供对类型参数的访问(类本身中声明的内容,而不是在此特定具体化调用站点中传递的实际类型)。

您不应该为此使用该类,但 Type/KType反而。有方便typeOf函数在具体化类型上访问它,然后您可以通过 arguments 访问类型参数属性:

val typeArgs = typeOf<T>().arguments

一旦有了这些,您就可以像在现有代码中一样访问它们的类型和该类型的分类器,但这次它将是实际类型参数的类型。

inline fun <reified T : Any> getRequiredVariable(variableName: String) =
    if (T::class.isSubclassOf(List::class)) {
        val itemTypeProjection = typeOf<T>().arguments[0]
        val itemType = itemTypeProjection.type ?: error("Cannot get list item type from List<*>")
        val itemKClass = itemType.classifier as? KClass<*> ?: error("The list item type is not denotable in Kotlin")
        getRequiredListVariable(variableName, itemKClass) as? T
    } else {
        getRequiredVariable(variableName, T::class)
    }

但是请注意,访问类型参数 0 通常不会为您提供 List 的任何实现类的项类型。 。例如,如果类型为 class MyStringList : List<String> ,它没有类型参数,但它是 List 的子类型。更糟糕的是,它可能有一个与列表元素无关的类型参数,如 class MyWeirdClass<X> : List<String> 中所示。 (使用 X 表示不相关的事情)。为了克服这个问题,您可能需要沿着父类(super class)型的层次结构向上查找 List 的类型。 T声明中使用的接口(interface)的类型 - 这可能会很痛苦。

关于kotlin - 获取具体化泛型类型的具体化类型参数kclass,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73709189/

相关文章:

java - 如何将 `MyClass` 添加到 `List<? extends MyClass>`

c# - 在为 aspx 页面编译动态程序集期间未触发 AssemblyResolve 事件

reflection - 如何使用反射检查接口(interface)是否指定方法

Java/Kotlin/Spring Boot。如何在异常发生时自动获取参数值?

java - 在 Java 中创建泛型类实例的正确方法是什么?

java - 如何将列表作为 JUnit5 的参数化测试参数传递?

java - 在方法中输入参数

java - 动态修改字段注解值

android - 为什么 fragment 中 `by lazy` 委托(delegate)的这种奇怪行为

kotlin - 为什么 smart-cast 不处理这种情况?