Kotlin:Intrinsics.areEqual无限循环(堆栈溢出)
java.lang.StackOverflowError at kotlin.jvm.internal.Intrinsics.areEqual(Intrinsics.java:164) at plugin.interaction.inter.teleports.Category.equals(Category.kt) at kotlin.jvm.internal.Intrinsics.areEqual(Intrinsics.java:164) at plugin.interaction.inter.teleports.Destination.equals(Destination.kt)
从两个非关系数据类之间的.equals
比较中发生。
主要的错误。
data class Category(val name: String, val destinations: MutableList<Destination>) data class Destination(val category: Category, val name: String)
Kotlin中的数据类只是Java POJO的语法糖。
在你的例子中,罪魁祸首就是这个循环:
val destinations: MutableList<Destination>
in Category
&
val category: Category
Destination
val category: Category
您必须通过将两个变量之一移出主数据类构造函数来删除此循环。
然而,还有一个更大的副作用: data class Category(..)
是可变的 ,这将导致它(以及任何其他数据类使用它的主要构造函数中的类)在任何哈希函数中作为键是不安全的,基于收藏。 有关更多信息,请参阅: 可变的hashmap键是否是危险的练习?
鉴于数据类是用于纯数据的,我建议删除val category: Category
data class Destination(..)
val category: Category
,并将val destinations: MutableList<Destination>
类型更改为val destinations: MutableList<Destination>
in data class Category(..)
to read-only List<Destination>
。 为了在修改之后破坏不可变的状态,你必须从Kotlin执行不安全的强制转换,或者从Java创建一个类的实例。
如果你绝对需要反向引用目录中的类别(而不是在hashmaps / -sets / etc中使用你的类),你可以使Destination成为一个普通的类,并且自己实现equals / hashCode,或者把类别移出主要的构造函数。 这有点棘手,但可以使用辅助构造函数完成:
data class Destination private constructor(val name: String) { private lateinit var _category: Category val category get() = _category constructor(category: Category, name: String) : this(name) { _category = category } }