问题
I have a data class like this
data class Person(val id: Long = BaseDataContract.BaseData.UNDEFINED_ID.toLong(),
.....
val personConsents: ArrayList<PersonConsent> = ArrayList<PersonConsent>())
I have two copies of the object:
person = originalPerson.copy()
Then I change the elements of personConsents for the object person - I add/delete/edit them.
But by some reason I see that the same changes are happening in originalPerson object which I don't want to be. originalPerson is not supposed to be changed at all.
Suspect there is something with ArrayList references, but need your advice what i can do? At the end I need to compare two objects likefun dataChanged(): Boolean = originalPerson != person
bu it doesn't work when ArrayList is changing.
回答1:
I found a simple solution. I use my own clone function which creates a new object for ArrayList and fill it by copied elements.
fun getPersonClone(person: Person): Person {
val personConsents: ArrayList<PersonConsent> = ArrayList<PersonConsent>()
person.personConsents.forEach { personConsents.add(it.copy()) }
return Person(person.id, ......., personConsents)
}
回答2:
So,this link here, will help you understand that the copy
method in Kotlin, does not do a deep copy, it only does a shallow one. This is specially seen with non-primitive data types such as the ArrayList
one you're using.
If you must use a method to copy the data class directly, what you can do is serialize it, and then de-serialize it.
I've done something like this below, using Gson
.
Using the Data Class
data class Person(var name: String? = null,val cars : ArrayList<String> = ArrayList() )
The main method
fun main (args: Array<String>) {
var original =Person("Jon", arrayListOf("Honda City","VW Vento"))
var clone =Gson().fromJson(Gson().toJson(original), Person::class.java)
original.cars.add("VW Polo")
original.name = "Henry"
print(clone.cars) // Prints [Honda City, VW Vento]
}
This approach seems really hacky, and I'd encourage anything better.
回答3:
The Kotlin copy method is a shallow copy. So your copy ends up referencing the exact same array as the original object.
I would say the simplest way to fix this is to implement the copy method yourself (no need to create an extra custom clone method):
data class Person(val id: Long = BaseDataContract.BaseData.UNDEFINED_ID.toLong(), val personConsents: ArrayList<PersonConsent> = ArrayList<PersonConsent>()) {
fun copy() = Person(this.id, ArrayList(this.personConsents))
}
来源:https://stackoverflow.com/questions/48681256/dataclass-copy-with-field-arraylist-change-the-arraylist-of-the-copied-class-c