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: Category
在 Destination
您必须通过将两个变量中的任何一个移出主数据 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
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: Category
在 Destination
您必须通过将两个变量中的任何一个移出主数据 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.
如果您绝对需要对目的地类别的反向引用(并且没有在 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 trueYou can check reference here