dataclass copy with field ArrayList - change the ArrayList of the copied class changes the original

假装没事ソ 提交于 2020-05-31 07:02:49

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!