【问题标题】:Kotlin language get class at runtimeKotlin 语言在运行时获取类
【发布时间】:2017-06-15 19:08:54
【问题描述】:

假设我们有以下内容:

val person = "Bill"

谁能解释一下这两者的区别:

val kClass1 = person.javaClass.kotlin    

对比

val kClass2 = person::class

我什么时候应该调用一个而不是另一个?

任何源代码示例都将不胜感激。

【问题讨论】:

    标签: reflection kotlin


    【解决方案1】:

    有两种方法可以实现同一件事,即获取对象的 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.kotlinx::class)在生成的字节码和运行时性能方面完全等效。我更喜欢x::class,因为它更短且阅读效果更好。

    【讨论】:

      【解决方案2】:

      person.javaClass.kotlin 从 Java 类创建新的 Kotlin 类引用对象。所以只有当你只有 java 类对象时才有意义。

      所以你应该使用person::class,因为在这种情况下你只需要直接获得 Kotlin 类而无需额外的对象分配

      【讨论】:

      • 在序列化中,“Kotlin in Action”的作者更喜欢“person.javaClass.kotlin”而不是“person::class”。为什么作者不喜欢“::class”?
      • 在“Kotlin in Action”中,我只看到一次提到了javaClass.kotlin ,这是一个如何从 Class 中获取 KClass 的示例
      • 这只是一个例子。这是“Kotlin in Action”中关于此代码片段的段落:“您可以通过编写 MyClass::class 来获取 KClass 的实例。要在运行时获取对象的类,首先您使用 javaClass 属性获取其 Java 类,它直接等效于 Java 的 java.lang.Object.getClass()。然后您访问 .kotlin 扩展属性以从 Java 迁移到 Kotlin 反射 API"
      【解决方案3】:

      没有人可以替代另一个人,他们都有存在的理由。

      如果你从一个不能是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
      • @Saxintosh 这很有趣,它似乎有所不同。 pl.kotl.in/cCAS9ewlL 打印“false”,表明这个答案是正确的(你错了)。但是,使用相同版本的 Kotlin 编译但在我的本地计算机上运行的相同文件打印“true”。
      • 是的!由于 .kotlin 的实现依赖于Reflection.getOrCreateKotlinClass(),它会有所不同
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-03
      相关资源
      最近更新 更多