【问题标题】:dataclass copy with field ArrayList - change the ArrayList of the copied class changes the original带有字段 ArrayList 的数据类复制 - 更改复制类的 ArrayList 更改原始
【发布时间】:2018-02-08 08:51:58
【问题描述】:

我有一个这样的数据类

data class Person(val id: Long = BaseDataContract.BaseData.UNDEFINED_ID.toLong(),
              .....
              val personConsents: ArrayList<PersonConsent> = ArrayList<PersonConsent>()) 

我有两个对象副本:

person = originalPerson.copy()

然后我为对象 person 更改 personConsents 的元素 - 我添加/删除/编辑它们。 但是由于某种原因,我看到 originalPerson 对象中发生了我不想成为的相同变化。 originalPerson 根本不应该改变。 怀疑 ArrayList 引用有问题,但需要您的建议我能做什么?最后,我需要比较两个对象,例如fun dataChanged(): Boolean = originalPerson != person,但是当 ArrayList 发生变化时它不起作用。

【问题讨论】:

标签: arraylist kotlin copy data-class


【解决方案1】:

我找到了一个简单的解决方案。我使用自己的克隆函数为 ArrayList 创建一个新对象并用复制的元素填充它。

fun getPersonClone(person: Person): Person {
    val personConsents: ArrayList<PersonConsent> = ArrayList<PersonConsent>()
    person.personConsents.forEach { personConsents.add(it.copy()) }
    return Person(person.id, ......., personConsents)
}

【讨论】:

    【解决方案2】:

    所以,this link here,将帮助您了解 Kotlin 中的 copy 方法不做深拷贝,它只做浅拷贝。这特别适用于非原始数据类型,例如您正在使用的 ArrayList

    如果一定要用方法直接复制数据类,可以先序列化,再反序列化。

    我在下面使用Gson 完成了类似的操作。

    使用数据类

     data class Person(var name: String? = null,val cars : ArrayList<String> = ArrayList() )
    

    主要方法

    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]   
    
    }
    

    这种方法看起来很老套,我会鼓励任何更好的方法。

    【讨论】:

    • 感谢您的回答,但不想做诸如 hacky triks 之类的事情。将尝试找到更好的解决方案。至少我可以创建一个单独的 ArrayList 对象来将元素与 person.ArrayList 的元素进行比较
    【解决方案3】:

    Kotlin 复制方法是浅复制。因此,您的副本最终会引用与原始对象完全相同的数组。

    我想说解决这个问题的最简单方法是自己实现复制方法(无需创建额外的自定义克隆方法):

    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))
    }
    

    【讨论】:

      猜你喜欢
      • 2013-05-09
      • 2017-10-09
      • 2019-01-09
      • 1970-01-01
      • 1970-01-01
      • 2021-01-18
      • 2019-01-21
      • 2014-01-07
      相关资源
      最近更新 更多