Kotlin数据类拷贝方法不是深拷贝所有成员

有人可以解释Kotlin数据类的copy方法是如何工作的吗? 对于一些成员来说,(深)副本似乎并没有真正创建,而且引用仍然是原来的。

 fun test() { val bar = Bar(0) val foo = Foo(5, bar, mutableListOf(1, 2, 3)) println("foo : $foo") val barCopy = bar.copy() val fooCopy = foo.copy() foo.a = 10 bar.x = 2 foo.list.add(4) println("foo : $foo") println("fooCopy: $fooCopy") println("barCopy: $barCopy") } data class Foo(var a: Int, val bar: Bar, val list: MutableList = mutableListOf()) data class Bar(var x: Int = 0) 

输出:
foo:Foo(a = 5,bar = Bar(x = 0),list = [1,2,3])
foo:Foo(a = 10,bar = Bar(x = 2),list = [1,2,3,4])
fooCopy:Foo(a = 5,bar = Bar(x = 2),list = [1,2,3,4])
barCopy:Bar(x = 0)

为什么是barCopy.x=0 (预期),但fooCopy.bar.x=2 (我认为这将是0)。 因为Bar也是一个数据类,所以当foo.copy()被执行时,我希望foo.bar也是一个副本。

要深入复制所有成员,我可以这样做:

 val fooCopy = foo.copy(bar = foo.bar.copy(), list = foo.list.toMutableList()) 

fooCopy:Foo(a = 5,bar = Bar(x = 0),list = [1,2,3])

但是我是否错过了一些东西,还有没有更好的方法来做到这一点,而不需要指定这些成员需要强制复制?

Kotlin的copy方法根本不应该是一个深层次的复制。 如参考文档( https://kotlinlang.org/docs/reference/data-classes.html )中所述,对于类如下:

 data class User(val name: String = "", val age: Int = 0) 

copy实现将是:

 fun copy(name: String = this.name, age: Int = this.age) = User(name, age) 

所以你可以看到,这是一个浅的副本。 在你的具体情况下copy的实现将是:

 fun copy(a: Int = this.a, bar: Bar = this.bar, list: MutableList = this.list) = Foo(a, bar, list) fun copy(x: Int = this.x) = Bar(x) 

正如@Ekeko所说,为数据类实现的默认copy()函数是一个浅的副本,如下所示:

 fun copy(a: Int = this.a, bar: Bar = this.bar, list: MutableList = this.list) 

要执行深层复制,您必须覆盖copy()函数。

 fun copy(a: Int = this.a, bar: Bar = this.bar.copy(), list: MutableList = this.list.toList()) = Foo(a, bar, list)