KClass
定义为public interface KClass<T : Any> : KDeclarationContainer, KAnnotatedElement, KClassifier
这很棘手,因为 a 的类String?
应该是KClass<String>
,但不可能获得。
鉴于以下 3 个示例(它们应该都做基本相同的工作),其中 1 个无法编译,其他的返回相同的运行时类型。
inline fun <reified T> test1(): Any = T::class
inline fun <reified T: Any> test2(): KClass<T> = T::class
inline fun <reified T> test3(): KClass<T> = T::class // does not compile
test1<String?>() // class kotlin.String
test1<String>() // class kotlin.String
test2<String?>() // does not compile
test2<String>() // class kotlin.String
问题的关键是要问:我怎样才能获得test1
具有编译时行为(和安全性)的运行时行为test2
?
编辑:问题的最后一个附录是另一个示例,它演示了获取可为空类型的类的问题。
inline fun <reified T> test4() {
val x = T::class // compiles, implied type of x is KClass<T>
val y: KClass<T> = T::class // does not compile with explicit type of KClass<T>
}
我特别遇到问题的呼叫站点是:
class OutputContract<T>(
private val output: () -> T,
val outputType: KClass<T> // ERROR!
) {
fun invoke(): T {
return output()
}
}
inline fun <reified T> output(noinline output: () -> T): OutputContract<T> {
return OutputContract(output, T::class)
}
这里唯一的错误是 with KClass<T>
,而不是 with T::class
,这很好。我希望允许消费者将可空性指定为合同的一部分,因此添加Any
约束将不起作用。如果我只是KClass<T>
变成KClass<Any>
,这一切都有效(这证明没有运行时问题,只有编译时间)。这最终是我选择的解决方法,但如果我能真正保持正确的类型,那就太好了。