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 } } 
Interesting Posts