我正在对Kotlin的反思进行一些实验。
我试图通过其参数获得泛型类的反射对象。
在Java中,那将是ParameterizedType
。
使用Java反射API获取此类内容的方法有点复杂:创建泛型类的匿名子类,然后获取其超类型的第一个参数。
以下是一个例子:
@Suppress("unused") @PublishedApi
internal abstract class TypeReference<T> {}
inline fun <reified T> jGeneric() =
((object : TypeReference<T>() {}).javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0]
当我println(jGeneric<List<String?>>())
时,会打印java.util.List<? extends java.lang.String>
,这是合乎逻辑的,考虑到Kotlin的List
使用声明网站out
方差而且Java类型没有可空性的概念。
现在,我希望获得相同类型的结果,但使用Kotlin反射API(当然,它包含可空性信息)。
当然,List<String>::class
无效,因为它会产生KClass
。我正在寻找KType
。
然而,当我尝试这个时:
inline fun <reified T> kGeneric() =
(object : TypeReference<T>() {})::class.supertypes[0].arguments[0].type
当我println(kGeneric<List<String?>>())
时,会打印[ERROR : Unknown type parameter 0]
,这非常......好吧,虎头蛇尾;)
如何在Kotlin中获得KType
反映List<String>
?
答案 0 :(得分:5)
要在Kotlin 1.1中创建KType
实例,您有两种选择:
要从KClass
创建一个简单的非可空类型,其中该类不是通用的,或者您可以使用星形投影(*
)替换其所有类型参数,请使用starProjectedType
属性。例如,以下内容创建了一个代表非可空类型KType
的{{1}}:
String
或者,以下内容创建了一个代表非可空类型val nonNullStringType = String::class.starProjectedType
的{{1}}:
KType
对于更复杂的情况,请使用List<*>
功能。它接受类,类型参数以及类型是否应该为空。类型参数是val nonNullListOfSmth = List::class.starProjectedType
的列表,它只是一个类型+方差(in / out / none)。例如,以下代码创建表示createType
的{{1}}实例:
KTypeProjection
或者,以下内容创建类型KType
:
List<String>
val nonNullStringType = String::class.starProjectedType
val projection = KTypeProjection.invariant(nonNullStringType)
val listOfStrings = listClass.createType(listOf(projection))
和List<String>?
都在包val listOfStrings = listClass.createType(listOf(projection), nullable = true)
中定义。
We're planning介绍了简单地从内联函数的具体类型参数获取starProjectedType
实例的可能性,这有助于在某些情况下静态知道所需类型,但目前并不完全如果没有重大开销就可以清除。因此,在实施之前,请使用上述声明。