当前位置: 首页 > 知识库问答 >
问题:

如何在Kotlin中获得一个具体化的泛型参数的实际类型参数?

戎俊
2023-03-14
inline fun <reified T: Any> f() {
    val clazz = T::class
    // ...
}
f<List<Integer>>() // T::class is just kotlin.collections.List

是否有一种方法可以通过反射获得具体化泛型的实际类型参数?

共有1个答案

邢焕
2023-03-14

由于类型擦除,无法通过泛型类的t::class标记获得实际的泛型参数。一个类的不同对象必须具有相同的类标记,这就是为什么它不能包含实际的泛型参数。

但是有一种称为超级类型标记的技术,它可以在编译时知道类型的情况下给出实际的类型参数(由于内联,Kotlin中的具体化泛型也是如此)。

编辑:自从Kotlin 1.3.50之后,不再需要遵循下面描述的技术来获取具体化类型参数的类型信息。相反,您可以对具体化的类型参数使用typeof ()

abstract class TypeReference<T> : Comparable<TypeReference<T>> {
    val type: Type = 
        (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0]

    override fun compareTo(other: TypeReference<T>) = 0
}

在Jackson TypeReference中解释,它使用了相同的方法。Jackson Kotlin模块在reified泛型上使用它。

之后,在具有具体化泛型的内联函数中,需要对typereference进行子类化(对象表达式将会出现),然后可以使用其类型

示例:

inline fun <reified T: Any> printGenerics() {
    val type = object : TypeReference<T>() {}.type
    if (type is ParameterizedType)
        type.actualTypeArguments.forEach { println(it.typeName) }
}
java.lang.Integer
java.util.List<? extends java.lang.String>
 类似资料:
  • 只能在类文本的左侧使用类 是否可以像在C#中那样对泛型参数提供类约束,或者是否可以使用其他语法来获取泛型参数的类型信息?

  • 问题内容: 我有一个参数化的类: 致电: 那么,如何使用Java泛型来获取实际的类型? 问题答案: 可以做到,但是类型擦除可能会很困难。正如其他答案所讨论的那样,您必须成为的子类或将类型的字段添加到中,而执行此操作所需的反射代码却很复杂。 在这种情况下,我建议您解决以下问题: 由于Java对静态方法的类型推断,因此无需太多额外的样板即可构造类: 这样,您就具有完全的通用性和类型安全性,并且仍然可以

  • 问题内容: 我有一个像这样的课程: 但是编译器说:。 我如何获得的课程? 问题答案: 绝对有可能将其提取出来,因为它不是在运行时定义的,而是在编译时由定义的。 这是一个启动示例,您可以如何在抽象类的构造函数中提取所需的泛型超类型,同时考虑子类的层次结构(以及在无需显式提供类型的情况下将其应用于泛型方法的实际用例)):

  • 我不熟悉泛型。我有一个抽象类(1)和一个抽象方法。我有另一个抽象类(2)和一些抽象方法,我希望在一些DTO(3,4)中共享这些抽象方法。我想要一个(1)的具体扩展来处理任何扩展(2)的东西。 1. 扩展StagingError的两个类:3.

  • 我遇到了一个奇怪的行为,在类型为“具体化”的函数中使用Gson进行反序列化。仅当类型参数中涉及接口时才会发生这种情况。 采用以下代码: 第4行使用自定义扩展函数Gson。fromJson(json:String):T。 如果定义为具体化,则失败: 如果它被定义为普通类型参数,它就可以工作: (注意,使具体化在这里没有意义,只是想了解它在特殊用例中的影响) 使用具体化时的异常如下所示:

  • 问题是: 创建一个名为Duo的泛型类,它有两个参数a和B。声明一个名为a类型的第一个变量,以及一个名为B类型的第二个变量。创建一个接受这两个参数的构造函数。在构造函数中,将这些参数分别分配给声明的变量。 这是我能想到的解决方案: 然后,当我继续问下一个问题时,我被绊住了。问题是: 使用问题4中的Duo类声明并创建两个对象,如下所示: a) 第一个名为sideShape的对象分别由字符串类型和整数类