Kotlin:Intrinsics.areEqual 无限循环(堆栈溢出)

Kotlin: Intrinsics.areEqual infinite loop (stack overflow)

java.lang.WhosebugError
    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)

Data classes in Kotlin are just syntactic sugar for Java POJOs.

你的例子中的罪魁祸首是这个循环:

val destinations: MutableList<Destination>Category &
val category: CategoryDestination

您必须通过将两个变量中的任何一个移出主数据 class 构造函数来移除此循环。

然而,还有一个 更大的副作用:data class Category(..) 可变的 ,这将导致它(并且任何其他数据 class 在其主构造函数中使用类别!)在任何基于散列的集合中用作键是不安全的。有关详细信息,请参阅:Are mutable hashmap keys a dangerous practice?

鉴于数据 class 是纯数据,我建议删除 data class Destination(..) 中的 val category: Category,并更改 data class Category(..) 中的 val destinations: MutableList<Destination> 类型为只读 List<Destination>。为了在上述更改后打破不可变状态,您将不得不从 Kotlin 执行不安全的转换或从 Java.

创建 class 的实例

如果您绝对需要对目的地类别的反向引用(并且没有在 hashmaps/-sets/etc 中使用您的 classes),您可以将 Destination 设置为常规 class并自己实现 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
    }
}

嗯,在我的例子中,我重写了 equals 方法,例如:

override fun equals(other: Any?): Boolean {
        // some code here
        if (other==this)
            return true
       // some code here
    }

等于 java

中的 ==

在 java 中,当我们使用 equals(例如:str1.equals(str2))时,它会检查两个对象的内容(对于自定义对象,您必须覆盖 equals 并检查对象的所有值,否则对象 class 的 equals 方法只是比较引用,这与 == 相同),但是如果我们使用 ==(例如:str1==str2)运算符,它会检查两者的引用对象。


== 在科特林中

但是在 kotlin 的情况下,当我们使用 == 运算符时,它仅在对象是数据对象时才检查对象的内容(数据或变量)class。并且 == 运算符检查正常 class.

的引用

当我们使用==时,它会调用equals方法。


所以在我重写的 equals 方法中,当 other==this 执行时,它将再次调用 eaquals 方法,这将再次调用 eaquals 方法并进行无限循环。

所以为了让它工作,我们需要将 == 更改为 ===(这将检查两个运算符的引用),例如:

 if (other===this)
     return true

Note: .equals and == are same until we use them with Float or Double. .equals disagrees with the IEEE 754 Standard for Floating-Point Arithmetic, it returns a false when -0.0 was compared with 0.0 whereas == and === returns true

You can check reference here