数组的浅拷贝,为什么不能简单地做newArr = oldArr?

one*_*ece 6 java deep-copy shallow-copy

假设我有一个整数数组,"orig"

我想浅浅地复制它,所以我不能这样做:

int[] shallow = orig;
Run Code Online (Sandbox Code Playgroud)

我的教授说,对于原语,浅和深拷贝基本相同,因为我们必须复制数组的每个索引.但是将整个数组设置为另一个数组也是一样的,对吧?

我对对象数组有类似的问题

这是我的意识形态

Book[] objArr2 = objArr1;
Run Code Online (Sandbox Code Playgroud)

但有人告诉我,我必须复制每个数组索引,比如

//for loop
objArr2[i] = objArr1[i];
Run Code Online (Sandbox Code Playgroud)

对于浅层复制,将数组等同于另一个数组和单独复制每个数组索引之间是否存在任何差异?(我明白,深意味着你必须创建全新的对象)

Viv*_*ath 17

我想浅浅地复制它,所以我不能这样做:

int [] shallow = orig;

这不是一个浅薄的副本.副本是与原始类似的离散实体,但不是原始项.在您的示例中,您实际拥有的是两个指向同一对象的引用.创建副本时,应该有两个结果对象:原始对象和副本.

在这里,您要修改的任何内容shallow都会发生,orig因为它们都指向同一个对象.

当您比较的对象引用其中的其他对象时,"Shallowness"就会起作用.例如,如果您有一个整数数组并且您创建了一个副本,那么现在有两个数组都包含相同的整数值:

Original Array

[0]
[1]
[2]
[3]

After copying:

[0] <--- Original  [0]
[1]                [1]
[3]                [2]
[4]      Copy ---> [3]
Run Code Online (Sandbox Code Playgroud)

但是,如果你有一个由对象组成的数组(让我们说objArr1objArr2),该怎么办?当您执行浅复制时,您现在有两个新的数组对象,但两个数组之间的每个对应条目都指向同一个对象(因为对象本身尚未复制;只有引用具有).

Original Array:

[0:]----> [object 0]
[1:]----> [object 1]
[2:]----> [object 2]
[3:]----> [object 3]
Run Code Online (Sandbox Code Playgroud)

复制后(注意相应位置如何指向相同的实例):

Original -> [0:]----> [object 0] <----[:0] <- Copy
            [1:]----> [object 1] <----[:1]
            [2:]----> [object 2] <----[:2]
            [3:]----> [object 3] <----[:3]
Run Code Online (Sandbox Code Playgroud)

现在,如果您objArr1通过替换条目或删除条目进行修改,那么同样的事情就不会发生objArr2.但是,如果您修改对象objArr1[0],则会反映出来,objArr2[0]因为这些位置指向同一个对象.因此,在这种情况下,即使容器对象本身是不同的,它们包含的内容也是对同一对象的引用.

执行深层复制时,将有两个新阵列,其中每个对应的位置指向不同的实例.所以基本上你一直在制作对象的副本.

我的教授说,对于原语,浅和深拷贝基本相同,因为我们必须复制数组的每个索引.

要做的重要区别是,当您复制基元数组时,您将完全复制这些值.每次你得到一个新的原语.但是,当您拥有一个对象数组时,您真正拥有的是对象的引用数组.因此,当您创建副本时,您所做的就是创建一个数组,其中包含原始数组中引用的副本.但是,这些引用的新副本仍然指向相同的对应对象.这就是所谓的浅拷贝.如果您深度复制了数组,那么每个单独位置引用的对象也将被复制.所以你会看到这样的东西:

Original -> [0:]----> [object 0] Copy -> [0:]----> [copy of object 0]
            [1:]----> [object 1]         [1:]----> [copy of object 1]
            [2:]----> [object 2]         [2:]----> [copy of object 2]
            [3:]----> [object 3]         [3:]----> [copy of object 3]
Run Code Online (Sandbox Code Playgroud)

但是将整个数组设置为另一个数组也是一样的,对吧?

不,不是的.你在这里做的只是创建一个现有数组的新引用:

arr1 -> [0, 1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

现在让我们说你做到了arr2 = arr1.你有的是:

arr1 -> [0, 1, 2, 3, 4] <- arr2
Run Code Online (Sandbox Code Playgroud)

所以这两个arr1,并arr2指向同一个数组.因此,arr1当您使用arr2相同的数组访问数组时,将反映您执行的任何修改.复制时不会发生这种情况.