在Kotlin中,浅拷贝 创建了一个新对象,但嵌套对象(如集合元素或引用字段)并没有被复制,而是引用同样的对象,如原始实例。深拷贝 意味着递归复制所有嵌套对象(对象图),使得原始对象和副本完全独立。
在Kotlin的标准库中,没有通用的深拷贝工具,尤其是对于复杂结构或循环图,必须手动实现。
data class Person(val name: String, val addresses: List<String>) val original = Person("Anna", listOf("Moscow", "London")) val shallow = original.copy() println(original.addresses === shallow.addresses) // true, 是同一个引用
data class Person(val name: String, val addresses: List<String>) { fun deepCopy(): Person = Person(name, addresses.toList()) } val deep = original.deepCopy() printfn(original.addresses === deep.addresses) // false, 列表的新副本
如果对嵌套集合的data class使用
.copy(),集合会被复制吗?为什么?
不,copy()创建了一个浅拷贝。嵌套集合和对象仍然引用相同的对象。对这些对象的任何修改都会在原始对象和副本中可见,这可能导致bug。
data class Box(val items: MutableList<String>) val box1 = Box(mutableListOf("A")) val box2 = box1.copy() box2.items.add("B") printfn(box1.items) // [A, B] — 原始对象也被修改了!
故事
在一个项目中,通过普通的
.copy()data class保存对象状态,认为得到了一个"快照"。当返回到旧状态时,发现嵌套列表(mutableList)由于浅拷贝而在所有副本中被更改。
故事
在文档系统中,通过Gson的序列化/反序列化复制实体,期待深度复制,但nullable字段和日期序列化不正确,导致出现不正确的值和业务逻辑错误。
故事
在将状态迁移到类似Redux的Android开发store时,开始对状态树使用
copy(),期待副本完全独立。结果,一条store分支可能会由于引用相同的内部mutable集合而改变另一条状态。