【发布时间】:2017-06-15 19:08:54
【问题描述】:
假设我们有以下内容:
val person = "Bill"
谁能解释一下这两者的区别:
val kClass1 = person.javaClass.kotlin
对比
val kClass2 = person::class
我什么时候应该调用一个而不是另一个?
任何源代码示例都将不胜感激。
【问题讨论】:
标签: reflection kotlin
假设我们有以下内容:
val person = "Bill"
谁能解释一下这两者的区别:
val kClass1 = person.javaClass.kotlin
对比
val kClass2 = person::class
我什么时候应该调用一个而不是另一个?
任何源代码示例都将不胜感激。
【问题讨论】:
标签: reflection kotlin
有两种方法可以实现同一件事,即获取对象的 Kotlin 类的主要原因是因为在 Kotlin 1.1 之前,::class 文字不支持其左侧的表达式。因此,如果您使用的是 Kotlin 1.0,您唯一的选择是 .javaClass.kotlin,否则您可以使用其中任何一个。这就是“Kotlin in Action”使用.javaClass.kotlin 语法的原因:它是在 Kotlin 1.1 发布之前编写的。
这些表达式的类型也有细微差别。比如下面的代码中
interface T
fun f1(x: T) = x::class
fun f2(x: T) = x.javaClass.kotlin
f1 的类型是 KClass<out T>,但 f2 的类型是 KClass<T>。这实际上是javaClass声明中的一个疏忽:KClass<out T>在这种情况下更正确,因为x的类不一定是T,也可以是T的子类。
否则这两个表达式(x.javaClass.kotlin 和x::class)在生成的字节码和运行时性能方面完全等效。我更喜欢x::class,因为它更短且阅读效果更好。
【讨论】:
person.javaClass.kotlin 从 Java 类创建新的 Kotlin 类引用对象。所以只有当你只有 java 类对象时才有意义。
所以你应该使用person::class,因为在这种情况下你只需要直接获得 Kotlin 类而无需额外的对象分配
【讨论】:
javaClass.kotlin ,这是一个如何从 Class 中获取 KClass 的示例
没有人可以替代另一个人,他们都有存在的理由。
如果你从一个不能是null的变量中得到一个KClass,那么你更喜欢使用foo::class,因为javaClass.kotlin每次都会创建一个新实例,例如:
assert(foo::class === foo::class);
assert(foo.javaClass.kotlin !== foo.javaClass.kotlin);
如果你从一个可以为空的变量中得到一个KClass 然后更喜欢使用如下:
val value:Int? = 1;
val type = value?.javaClass?.kotlin;
如果你从 kotlin 得到一个 java Class 你想转换为 KClass 然后使用 Class.kotlin 例如:
val javaClass:Class<Integer> = ...;
val kotlinClass:KClass<Integer> = javaClass.kotlin;
【讨论】:
.foo.javaClass.kotlin === foo.javaClass.kotlin
Reflection.getOrCreateKotlinClass(),它会有所不同