如何在 Kotlin 中获取 KType?

How to obtain a KType in Kotlin?

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

假设我有一个 class 将短语映射到对象工厂。如果出现歧义,用户可以提供一个 type 参数,将搜索范围缩小到 return 那种类型的对象(或某些子类型)的工厂。

fun mapToFactory(phrase: Phrase,
          type: KType = Any::class): Any {...}

type 需要接受几乎任何东西,包括 Int,根据我的经验,它似乎被特殊对待。默认情况下,它应该类似于 Any,这意味着 "do not exclude any factories".

如何为 type 分配默认值(或任何值)?

根据您的描述,听起来您的函数应该采用 KClass 参数,而不是 KType,并使用 isSubclass 而不是 isSubtype 检查传入的对象。

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

不过,要回答您最初的问题,您可以使用 createType():

KClass 创建一个 KType
val type: KType = Any::class.createType()

请注意,如果 class 是泛型,则需要传递泛型参数的类型投影。在简单的情况下(所有类型变量都可以用星形投影代替),starProjectedType 也可以。有关 createTypestarProjectedType.

的更多信息

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

val int: KType = typeOf<Int>()

T::class.createType()相反,它支持嵌套的泛型参数:

val listOfString: KType = typeOf<List<String>>()

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

inline fun <reified T> printType() {
    val type = typeOf<T>()
    println(type.toString())
}

用法示例:

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

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

另请参阅: