我有一个关于 Kotlin 中数据类的问题。
假设我们有两个带有循环引用的类:
data class Foo(
var bar: Bar? = null
)
Run Code Online (Sandbox Code Playgroud)
data class Bar (
var foo: Foo? = null
)
Run Code Online (Sandbox Code Playgroud)
和主要功能:
fun main() {
val f = Foo()
val b = Bar()
f.bar = b
b.foo = f
f.hashCode()
b.hashCode()
//println(f)
//println(b)
}
Run Code Online (Sandbox Code Playgroud)
Kotlin 自动生成的代码将使 main 函数进入堆栈溢出。你可以在Kotlin Playground试试这个。
这是预期的行为吗?请注意,这是一个基本示例,但这将发生在现实生活中,例如,在 Bar 中,我们可以拥有 List、Set 或 Foo 的泛型集合,而不是对 Foo 的引用。
Kotlin 不应该产生某种编译器错误,或者即使在其他语言中也会发生这种情况?
同样的事情,但在 Java 中
这可能被认为是一个错误。这里是与 Kotlin 开发人员的通信,讨论了可能是另一个错误的问题,但重要的是:
\n\n\n默认情况下,不会生成特定的 equals 和 hashCode(因此,它们检查对象身份)。
\n对于 数据 类,hashCode 和 equals 基于属性值。\nI\xe2\x80\x99 会用文字而不是伪代码编写算法步骤:
\n哈希码:
\n\n
\n- 计算当前类中声明为构造函数参数的每个属性的 hashCode
\n- 返回 h1 \xc3\x97 31n\xe2\x88\x921 + h2 \xc3\x97 31n\xe2\x88\x922 + \xe2\x80\xa6 + hn
\n
这就是预期的行为,并且显然会在步骤 1 中破坏您的示例。在您的“真实”世界示例中,使用可能Array.hashCode是解决方案,但似乎在这个人为的示例中(尽管我已经看到了诸如此类的构造, \ 这就是 C/++ 中存在前向声明的原因...)。我会将其提交到https://youtrack.jetbrains.com/issues。他们可能只是告诉您使用对象 ID 将常规类的 hashCode 设置为默认值。
poipoi发现这实际上是几年前报道的,我错过了:https ://youtrack.jetbrains.com/issue/KT-16244
\n因此具有循环引用的数据类必须提供自己的toString和hashCode。可惜这不是记录在案的行为。
| 归档时间: |
|
| 查看次数: |
158 次 |
| 最近记录: |