简体   繁体   English

深拷贝和浅拷贝Java

[英]Deep Copy and Shallow Copy Java

I am studying for a java exam and what I found out practically differed from what is taught in theory. 我正在攻读java考试,我发现的几乎与理论教学不同。

Below is code: 以下是代码:

    StringBuilder num3[]= new StringBuilder[2];
    num3[0]= new StringBuilder("Pine");
    num3[1]= new StringBuilder("Oak");
    StringBuilder num4[] = new StringBuilder[2];
    System.arraycopy(num3, 0, num4, 0, 2);
    System.out.println(num3[0]==num4[0]);
    System.out.println(num4[0]);
    num3[0] = new StringBuilder("Choc"); 
    System.out.println(num3[0]);
    System.out.println(num4[0]);

The output is: 输出是:

true
Pine
Choc
Pine

The true statement indicates that it is a shallow copy as num4[0] references the same object of num3[0]. 真实的陈述表明它是浅拷贝,因为num4 [0]引用num3 [0]的相同对象。 But when I change the num3[0] I expected num4[0] to change too. 但是当我更改num3 [0]时,我预期num4 [0]也会改变。

Why would this be happening if it is a shallow copy? 如果它是浅拷贝,为什么会发生这种情况呢?

Is it because the new object is being created for num3[0] and the old "Pine" StringBuilder object is being referenced by the num4 array? 是因为为num3 [0]创建了新对象,而num4数组正在引用旧的“Pine”StringBuilder对象?

If so could anyone give me an example for System.arraycopy where this shallow copy is evident? 如果是这样,任何人都可以给我一个System.arraycopy的例子,这个浅拷贝很明显吗?

Thanks in advance, Chrisyopher 谢谢你,克里斯托弗

After the System.arraycopy , the two arrays are indeed shallow copies of each other. System.arraycopy ,两个数组确实是彼此的浅层副本。 That is, you had a copy of the references to the StringBuilder s. 也就是说,你有一个StringBuilder 引用的副本。 The objects referred to are the same. 提到的对象是相同的。

num3:  [ refA, refB ]                        num4: [ refA, refB ]
           |    |                                      |     |
           |    `-------> StringBuilder("Oak") <-------+-----' 
           `------------> StringBuilder("Pine") <------'

But then you change the reference in num3[0] to point to a new StringBuilder : 但是然后你改变num3[0]引用指向一个新的StringBuilder

num3:  [ refC, refB ]                        num4: [ refA, refB ]
           |    |                                      |     |
           |    `-------> StringBuilder("Oak") <-------+-----' 
           |              StringBuilder("Pine") <------'
           `------------> StringBuilder("Choc")

The underlying objects haven't changed. 底层对象没有改变。 All you've done is changed what's referencing them. 你所做的一切都改变了引用它们的东西。


System.arraycopy is just like having a for loop that copies the values in the arrays over, except it's much more efficient for large arrays (as modern CPUs have special instructions for bulk memory copying). System.arraycopy就像有一个for循环复制数组中的值,除了它对大型数组更有效(因为现代CPU有大量内存复制的特殊指令)。 You don't ever need it semantically ; 你从不需要语义 ; it's just a performance optimisation. 这只是一次性能优化。

num3[0] and num4[0] are references to same object, so when you change the num3[0] it just changes where the num3[0] is pointing to and will not change where num4[0] is pointing. num3[0]num4[0]是对同一对象的引用,因此当你更改num3[0]它只会改变num3[0]指向的位置,而不会改变num4[0]所指向的位置。

System.out.println(num3[0]==num4[0]);

This returns true because both are pointing to same object but both are individual. 这返回true,因为两者都指向同一个对象,但两者都是个体。

If you would have done something like 如果你会做类似的事情

num3[0].append("something") and then you would have printed num3[0] and num4[0] then both would have been affected. num3[0].append("something")然后你会打印num3[0]num4[0]然后两者都会受到影响。

You are not changing num3[0], you are pointing it at something else, namely, a new StringBuilder object. 你没有改变num3 [0],你指向别的东西,即一个新的StringBuilder对象。 num3[0] and num4[0] no longer point at the same object, hence why num4[0] doesn't change. num3 [0]和num4 [0]不再指向同一个对象,因此num4 [0]不会改变。 The values of the references of the array are copied, but if you modify those values it won't affect the other array. 将复制数组引用的值,但如果您修改这些值,则不会影响其他数组。 What would affect it is if you modify the objects at which they point, not the references to those objects. 影响它的是你修改它们指向的对象 ,而不是对这些对象的引用

Think of num3[0] and num4[0] as two guys pointing at a bagpack. 想想num3[0]num4[0]两个人指着一个背包。 If you add stuff to the backpack, they will both point at something that has been changed. 如果你在背包里添加东西,它们都会指向已经改变的东西。 However, if you ask num3[0] to point at a TV, num4[0] will still be pointing at the backpack. 但是,如果你要求num3[0]指向电视,num4 [0]仍将指向背包。

Is it because the new object is being created for num3[0] and the old "Pine" StringBuilder object is being referenced by the num4 array? 是因为为num3 [0]创建了新对象,而num4数组正在引用旧的“Pine”StringBuilder对象?

Exactly. 究竟。

If so could anyone give me an example for System.arraycopy where this shallow copy is evident? 如果是这样,任何人都可以给我一个System.arraycopy的例子,这个浅拷贝很明显吗?

I am not sure I understand this question. 我不确定我是否理解这个问题。 No copy, be it shallow or deep can have an influence on what you do after the copy. 没有副本,无论是浅薄还是深,都会对复制的操作产生影响。

But try the following: 但请尝试以下方法:

num3[1].append("tree");
println(num4[1]);        // should be "Oaktree"

A shallow copy in this case is nothing else than a new reference to the object. 在这种情况下,浅表副本只不过是对该对象的新引用。 You have the object Pine with one pointer to it stored int num3 . 你有一个对象Pine ,其中一个指针存储在num3 Now you make a shallow copy (you create a new reference) that is stored in num4 . 现在,您创建一个存储在num4的浅拷贝(您创建一个新的引用)。 You now have one Pine object with two references. 您现在有一个带有两个引用的Pine对象。 When you assign Choc to num3 the number of references decreases by 1 and you effectively replaced the reference held by num3 with a different one. Choc分配给num3 ,引用数减少1,并且您有效地将num3持有的引用替换为num3引用。 Pine was never changed in any way. Pine从未改变过任何方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM