Kotlin的反思:未知类型参数 [英] Kotlin's reflection : Unknown type parameter

查看:185
本文介绍了Kotlin的反思:未知类型参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在对科特林的倒影进行一些实验.

I am running some experiments on Kotlin's reflection.

我正在尝试使用其参数获取泛型类的反射对象.

I am trying to get a reflection object of a generic class with its argument.

在Java中,这将是ParameterizedType.

In Java, that would be a ParameterizedType.

使用Java的反射API来获取此类信息的方法有些复杂:创建泛型类的匿名子类,然后获取其超类型的第一个参数.

The way to get such a thing using Java's reflection API is a bit convoluted: create an anonymous subclass of a generic class, then get its super-type first parameter.

这是一个例子:

@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类型没有可空性的概念,这是合乎逻辑的.

When I println(jGeneric<List<String?>>()), it prints java.util.List<? extends java.lang.String>, which is logical considering that Kotlin's List uses declaration-site out variance and that Java types have no notion of nullability.

现在,我想获得相同的结果,但是要使用Kotlin反射API(当然,其中将包含可空性信息).

Now, I would like to achieve the same kind of result, but with the Kotlin reflection API (that would, of course, contain nullability information).

当然,List<String>::class无法工作,因为它会产生KClass.而我正在寻找KType.

Of course, List<String>::class cannot work since it yields a KClass. and I am looking for a KType.

但是,当我尝试此操作时:

However, when I try this:

inline fun <reified T> kGeneric() =
    (object : TypeReference<T>() {})::class.supertypes[0].arguments[0].type

当我println(kGeneric<List<String?>>())时,它会打印[ERROR : Unknown type parameter 0],这很...嗯,反斜杠;)

When I println(kGeneric<List<String?>>()), it prints [ERROR : Unknown type parameter 0], which is quite... well, anticlimactic ;)

如何在Kotlin中获得反映List<String>KType?

How can I get, in Kotlin, a KType reflecting List<String> ?

推荐答案

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

To create a KType instance in Kotlin 1.1, you have two options:

  • 要从KClass中创建简单的非空类型,其中该类不是通用的,或者可以将所有类型参数替换为星形投影(*),请使用starProjectedType财产.例如,下面的代码创建一个KType表示一个不可为null的类型String:

  • To create a simple non-nullable type out of a KClass, where the class is either not generic or you can substitute all its type parameters with star projections (*), use the starProjectedType property. For example, the following creates a KType representing a non-nullable type String:

val nonNullStringType = String::class.starProjectedType

或者,下面的代码创建一个KType表示一个不可为空的类型List<*>:

Or, the following creates a KType representing a non-nullable type List<*>:

val nonNullListOfSmth = List::class.starProjectedType

  • 对于更复杂的情况,请使用createType函数.它需要类,类型参数以及类型是否应为可为空.类型参数是KTypeProjection的列表,它只是类型+差异(输入/输出/无).例如,以下代码创建一个表示List<String>KType实例:

  • For more complex cases, use the createType function. It takes the class, type arguments and whether or not the type should be nullable. Type arguments are a list of KTypeProjection which is simply a type + variance (in/out/none). For example, the following code creates a KType instance representing 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)
    

  • starProjectedTypecreateType都在包kotlin.reflect.full中定义.

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

    We're planning to introduce the possibility of getting a KType instance simply from a reified type parameter of an inline function which would help in some cases where the needed type is known statically, however currently it's not entirely clear if that's possible without major overhead. So, until that's implemented, please use the declarations explained above.

    这篇关于Kotlin的反思:未知类型参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆