12

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

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

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

type需要接受任何东西,包括Int,根据我的经验,这似乎受到了一些特殊对待。默认情况下,它应该类似于Any,表示“不排除任何工厂”。

如何将默认值(或任何值)分配给type

4

2 回答 2

19

根据您的描述,听起来您的函数应该带一个KClass参数,而不是 a ,并使用,而不是KType检查传入的对象。isSubclassisSubtype

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

不过,要回答您最初的问题,您可以使用with创建一个KTypeout :KClasscreateType()

val type: KType = Any::class.createType()

请注意,如果该类是泛型的,则需要传递泛型参数的类型投影。在简单的情况下(所有类型变量都可以用星形投影替换),starProjectedType也可以工作。有关 and 的更多信息createTypestarProjectedType参阅此答案

于 2017-03-17T17:50:32.700 回答
13

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

val int: KType = typeOf<Int>()

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

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

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

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>
}

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

也可以看看:

于 2019-11-10T12:34:51.913 回答