gpt4 book ai didi

reflection - instance::class.java 与 instance.javaClass

转载 作者:IT老高 更新时间:2023-10-28 13:32:19 28 4
gpt4 key购买 nike

鉴于 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 以获得更高的一致性。有什么反对意见吗?

最佳答案

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

  • foo.javaClass键入为 Class<Foo>

  • foo::class.java键入为 Class<out Foo>

其实后者更精确,因为foo的实际值计算结果可以是 not Foo 的一个实例本身,但它的子类型之一(它正是由协变 out Foo 表示的)。

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

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


请注意 Int.javaClass不表示 Int 的类型而是 Int 的 Java 类的伴生对象。鉴于 Int::class.java是一个未绑定(bind)的类引用并表示类型。使用 .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<Foo> 然后转换为 KClass<Foo> )编译器允许我们将它与 in Foo 一起使用投影。

关于reflection - instance::class.java 与 instance.javaClass,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46674787/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com