Kotlin的反思:未知类型参数

时间:2017-05-26 13:49:09

标签: kotlin kotlin-reflect

我正在对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>

1 个答案:

答案 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实例的可能性,这有助于在某些情况下静态知道所需类型,但目前并不完全如果没有重大开销就可以清除。因此,在实施之前,请使用上述声明。