Kotlin的反思:未知的类型参数

Sal*_*RYS 1 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]
Run Code Online (Sandbox Code Playgroud)

当我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
Run Code Online (Sandbox Code Playgroud)

当我println(kGeneric<List<String?>>()),它打印[ERROR : Unknown type parameter 0],这是相当......好吧,虎头蛇尾;)

在Kotlin,我怎样才能得到一个KType反映List<String>

Ale*_*lov 6

KType在Kotlin 1.1中创建实例,您有两种选择:

  • 要创建一个简单的非可空类型KClass,其中类不是通用的,或者您可以使用星形投影(*)替换其所有类型参数,请使用该starProjectedType属性.例如,以下内容创建KType表示非可空类型String:

    val nonNullStringType = String::class.starProjectedType
    
    Run Code Online (Sandbox Code Playgroud)

    或者,以下创建KType表示不可为空的类型List<*>:

    val nonNullListOfSmth = List::class.starProjectedType
    
    Run Code Online (Sandbox Code Playgroud)
  • 对于更复杂的情况,请使用该createType功能.它接受类,类型参数以及类型是否应该为空.类型参数是一个列表,KTypeProjection它只是一个类型+方差(in/out/none).例如,以下代码创建一个KType表示以下内容的实例List<String>:

    val nonNullStringType = String::class.starProjectedType
    val projection = KTypeProjection.invariant(nonNullStringType)
    val listOfStrings = listClass.createType(listOf(projection))
    
    Run Code Online (Sandbox Code Playgroud)

    或者,以下创建类型List<String>?:

    val listOfStrings = listClass.createType(listOf(projection), nullable = true)
    
    Run Code Online (Sandbox Code Playgroud)

二者starProjectedTypecreateType在包中定义kotlin.reflect.full.

我们计划KType简单地从内联函数的reified类型参数中获取实例的可能性,这有助于在某些情况下静态地知道所需类型,但是目前还不完全清楚是否可能没有大的开销.因此,在实施之前,请使用上面说明的声明.