如何在 Kotlin 中获取 KType?

16

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

假设我有一个将短语映射到对象工厂的类。在存在歧义的情况下,用户可以提供一个 type 参数,该参数仅限于返回该类型对象(或某个子类型)的工厂进行搜索。

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

type 需要接受几乎任何东西,包括 Int ,根据我的经验,它似乎被特殊处理。 默认情况下,它应该是像 Any 这样的东西,这意味着“不排除任何工厂”。

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

2个回答

23
从你的描述来看,似乎你的函数应该接受一个 KClass 参数而不是一个 KType,并使用 isSubclass 而不是 isSubtype 来检查传入的对象。
类型(由 kotlin-reflect 中的 KType 表示)通常来自于你代码中声明的签名;它们表示函数作为参数或返回值所接受的一组广泛的值。一个类型由类、该类的泛型参数以及可空性组成。在 JVM 上运行时类型的问题在于,由于擦除,不可能确定泛型类变量的确切类型。例如,如果你有一个列表,你无法在运行时确定该列表的泛型类型,即你无法区分 List<String>List<Throwable>
不过,要回答你最初的问题,你可以使用 createType()KClass 创建为 KType
val type: KType = Any::class.createType()

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


16

自 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。
另请参见:

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接