如何在Kotlin中获得KType?

use*_*024 3 reflection kotlin kotlin-reflect

我正在试验Kotlin中的反射功能,但我似乎无法理解如何获取KType值.

假设我有一个将短语映射到对象工厂的类.在模糊的情况下,用户可以提供type将搜索范围缩小到仅返回该类型对象(或某些子类型)的工厂的参数.

fun mapToFactory(phrase: Phrase,
          type: KType = Any::class): Any {...}
Run Code Online (Sandbox Code Playgroud)

type我需要接受几乎任何东西,包括Int从我的经验中看起来有点特别对待.默认情况下,它应该是类似的Any,这意味着"不排除任何工厂".

如何为默认值(或任何值)指定type

Ale*_*lov 10

根据你的描述,你的函数听起来应该是一个KClass参数,而不是a KType,并检查传入的对象isSubclass,而不是isSubtype.

类型(由KTypein 表示kotlin-reflect)通常来自代码中的声明签名; 它们表示一组广泛的值,其函数作为参数或返回.类型由类,该类的泛型参数和可空性组成.JVM上运行时类型的问题在于,由于擦除,无法确定泛型类的变量的确切类型.例如,如果您有一个列表,则无法在运行时确定该列表的泛型类型,即您无法区分List<String>List<Throwable>.

为了虽然回答您最初的问题,您可以创建一个KType走出了一条KClass具有createType():

val type: KType = Any::class.createType()
Run Code Online (Sandbox Code Playgroud)

请注意,如果类是通用的,则需要传递泛型参数的类型投影.在简单的情况下(所有类型变量都可以用星形投影替换),starProjectedType也可以.有关更多信息createTypestarProjectedType,看到这个答案.


The*_*tor 8

从 Kotlin 1.3.40 开始,您可以使用实验函数typeOf<T>()来获取KType任何类型的 :

val int: KType = typeOf<Int>()
Run Code Online (Sandbox Code Playgroud)

与 相比T::class.createType(),这支持嵌套的泛型参数:

val listOfString: KType = typeOf<List<String>>()
Run Code Online (Sandbox Code Playgroud)

typeOf<T>()当您想KType从具体化的类型参数中获取 a 时,该函数特别有用:

inline fun <reified T> printType() {
    val type = typeOf<T>()
    println(type.toString())
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

fun main(args: Array<String>) {
    printType<Map<Int, String>>()
    // prints:   kotlin.collections.Map<kotlin.Int, kotlin.String>
}
Run Code Online (Sandbox Code Playgroud)

由于此功能仍处于实验状态,因此您需要在@UseExperimental(ExperimentalStdlibApi::class)使用typeOf<T>(). 随着功能变得更加稳定(可能在 Kotlin 1.4 中),这可以省略。此外,目前它仅适用于 Kotlin/JVM,不适用于 Kotlin/Native 或 Kotlin/JS。

也可以看看: