【问题标题】:instance::class.java vs. instance.javaClassinstance::class.java 与 instance.javaClass
【发布时间】:2017-10-10 19:48:08
【问题描述】:

鉴于 Kotlin 1.1。对于某个类的instanceinstance::class.javainstance.javaClass 似乎几乎是等价的:

val i = 0
println(i::class.java) // int
println(i.javaClass) // int
println(i::class.java === i.javaClass) // true

但是有一个细微的差别:

val c1: Class<out Int> = i::class.java
val c2: Class<Int> = i.javaClass

instance.javaClass 短到可以忽略不计,但instance::class.java 更符合类型的相应用法。虽然您可以在某些类型上使用.javaClass,但结果可能不是您所期望的:

println(i::class.java === Int::class.java) // true
println(i.javaClass === Int.javaClass) // false
println(Int::class.java === Int.javaClass) // false
println(Int.javaClass) // class kotlin.jvm.internal.IntCompanionObject

所以,我认为最好不要使用.javaClass 以获得更高的一致性。有什么反对意见吗?

【问题讨论】:

  • 我想我在某处读到过 javaClass 将被视为已弃用,但我现在找不到。
  • @marstran 只有重载KClass&lt;T&gt;.javaClass 已被弃用。 API reference

标签: reflection kotlin


【解决方案1】:

这两种构造的区别在于,对于静态(声明或推断)类型Foo 的表达式foo

  • foo.javaClass 输入为Class&lt;Foo&gt;

  • foo::class.java 输入为Class&lt;out Foo&gt;

事实上,后者更精确,因为foo 计算的实际值可能不是Foo 本身的实例,而是它的子类型之一(它正是协变out Foo 所表示的) .

正如@marstran 在对问题的评论中正确指出的那样,.javaClass 曾经被认为已被弃用(请参阅Kotlin 1.1 RC announcement),因为它可能会破坏类型安全(见下文),但后来被保留原样因为它被广泛使用,并且用 ::class.java 的替代品替换它需要在代码中添加明确的未经检查的强制转换。

另外,请参阅此答案下的 cmets:(link)


请注意Int.javaClass 不表示Int 的类型,而是Int 的伴随对象的Java 类。而Int::class.java 是一个未绑定的类引用并表示类型。要使用.javaClass 获取它,您需要在Int 实例上调用它,例如1.javaClass.


.javaClass 究竟是如何破坏类型安全的。此代码编译但在运行时中断:

open class Foo

class Bar : Foo() {
    val baz: Int = 0
}

fun main(args: Array<String>) {
    val someFoo: Foo = Bar()
    val anotherFoo: Foo = Foo()

    val someFooProperty: KProperty1<in Foo, *> = // 'in Foo' is bad
            someFoo.javaClass.kotlin.memberProperties.first()

    val someValue = someFooProperty.get(anotherFoo)
}

本例使用kotlin-reflect

那是因为someFooProperty 表示Bar 的属性,而不是Foo,但由于它是从someFoo.javaClass 获得的(Class&lt;Foo&gt; 然后转换为KClass&lt;Foo&gt;)编译器允许我们将它与in Foo 投影。

【讨论】:

  • 那为什么我必须在Android上使用::class.java来启动一个Activity(例如:startActivity(Intent(context,SomeActivity::class.java))?毕竟,它进入了 Java“世界”,不是吗?
猜你喜欢
  • 2017-07-12
  • 1970-01-01
  • 2021-10-11
  • 2016-05-31
  • 1970-01-01
  • 2015-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多