如何获得Kotlin中实际泛型参数的实际类型参数?

使用指定的类型参数 ,可以编写一个内联函数,它可以在运行时通过反射来处理类型参数:

inline fun <reified T: Any> f() { val clazz = T::class // ... } 

但是当用一个本身是一个泛型类的参数调用f时,似乎没有办法通过T::class获得它的实际类型参数:

 f<List<Integer>>() // T::class is just kotlin.collections.List 

有没有办法通过反射来获得实际的泛化类型的类型参数?

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

但是有一个称为超级类型标记的技术,当编译时已知类型时,它可以给出实际类型的参数(因为内联而在Kotlin中实现泛化的泛型)。

诀窍是编译器保留了从泛型类派生的非泛型类的实际类型参数(它的所有实例都有相同的参数, 这里有很好的解释)。 它们可以通过Class<*>实例的clazz.genericSuperClass.actualTypeArguments访问。

鉴于这一切,你可以写这样一个util类:

 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模块将其用于通用泛型。

之后,在具有泛化泛型的内联函数中, TypeReference需要被子类化( 对象表达式将会去),然后可以使用它的type

例:

 inline fun <reified T: Any> printGenerics() { val type = object : TypeReference<T>() {}.type if (type is ParameterizedType) type.actualTypeArguments.forEach { println(it.typeName) } } 

printGenerics<HashMap<Int, List<String>>>()

 java.lang.Integer java.util.List<? extends java.lang.String>