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)
Happens from a .equals
comparison between two non-relationship data classes.
Major bug.
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.
The main culprit in your example is this cycle:
val destinations: MutableList<Destination>
in Category
&val category: Category
in Destination
You must remove this cycle by moving either of the two variables out of the primary data class constructor.
However, there is also a much bigger sideeffect: data class Category(..)
is mutable, which will cause for it (and any other data class using categories in it's primary constructor!) to be unsafe to use as keys in any hash-based collection. For more information, see: Are mutable hashmap keys a dangerous practice?
Given that data classes are meant for pure data, I recommend removing val category: Category
in data class Destination(..)
, and change type of val destinations: MutableList<Destination>
in data class Category(..)
to read-only List<Destination>
. In order to break immutable state after said changes, you will have to either perform unsafe casts from Kotlin or create an instance of the class from Java.
If you however absolutely require a backreference to categories in destinations (and aren't using your classes in hashmaps/-sets/etc.), you could either make Destination a regular class and implement equals/hashCode yourself, or move the category out of the primary constructor. This is a bit tricky, but can be done with a secondary constructor:
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
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With