简体   繁体   English

Java的ArrayList的拷贝构造函数是浅拷贝还是深拷贝?

[英]Is the copy constructor of Java's ArrayList shallow copy or deep copy?

I have long being confused with whether Java's container's copy constructor is shallow copy or deep copy? 我一直对Java的容器的复制构造函数是浅拷贝还是深拷贝感到困惑? Below is my understanding: ints1, ints2, ints3 are references so they lie in stack. 以下是我的理解:ints1,ints2,ints3是引用,所以它们位于堆栈中。 inst1 points to some object in heap, and this object holds three anonymous references that lie in stack, and they point to Objects that have int value 0, 1, 2 seperately. inst1指向堆中的某个对象,该对象包含三个位于堆栈中的匿名引用,它们指向具有int值0,1,2的对象。

ints2 = ints1

so ints2 points to the same object as ints1. 所以ints2指向与ints1相同的对象。 So change objects pointed by refenences in ints2 will influence those in ints2. 因此,更改ints2中的refenences指向的对象将影响ints2中的那些对象。

ints2.set(1,0+10)

will change refenence ints1.get(0)'s object. 将改变refenence ints1.get(0)的对象。

ints3 = new ArrayList<>(ints1)

Next is my confusion. 接下来是我的困惑。

If copy constructor is shallow copy, then although ints1 and ints3 point to different object, the two objects have same references! 如果复制构造函数是浅复制,那么虽然ints1和ints3指向不同的对象,但这两个对象具有相同的引用! So any action to change objects by manipulating reference in ints1 will changes ints3, because they are pointing to the same objects. 因此,通过操作ints1中的引用来更改对象的任何操作都将更改ints3,因为它们指向相同的对象。

If copy constructor is deep copy, then ints1 and ints3 will hold different references and point to different objects. 如果复制构造函数是深层复制,则ints1和ints3将包含不同的引用并指向不同的对象。 Then the change in ints1 will not influence that in ints3. 那么ints1的变化不会影响ints3中的变化。

According to the result, it seems that the copy constructor is deep copy, not shallow copy. 根据结果​​,似乎复制构造函数是深拷贝,而不是浅拷贝。

Hope someone can correct me, thanks. 希望有人能纠正我,谢谢。

import java.util.*;
public class MyClass {
    public static void main(String args[]) {
       List<Integer> ints1 = new ArrayList<>(Arrays.asList(0,1,2));
       System.out.println(ints1);
       List<Integer> ints2 = ints1;
       ints2.set(0,0+10);
       System.out.println(ints1);
       List<Integer> ints3 = new ArrayList<>(ints1);
       ints3.set(1,1+10);
       System.out.println(ints1);
    }
}
result
[0, 1, 2]
[10, 1, 2]
[10, 1, 2]

The answer is : shallow copy. 答案是:浅拷贝。 Have a look at this post which gives more details on the topic: http://javarevisited.blogspot.co.uk/2014/03/how-to-clone-collection-in-java-deep-copy-vs-shallow.html?m=1 看一下这篇文章,它提供了有关该主题的更多细节: http//javarevisited.blogspot.co.uk/2014/03/how-to-clone-collection-in-java-deep-copy-vs-shallow。 HTML?m = 1的

The crux of the issue is that when you do ints3.set(1, 1+10) you are actually changing the reference that was stored in ints3[1] . 问题的关键在于当你执行ints3.set(1, 1+10)你实际上正在改变存储在ints3[1]的引用。 The reference stored in ints1[1] remains unaffected from this. 存储在ints1[1]的引用不受此影响。

// Format

 ---------- 
|  Value   |
 ---------- 
  Address


// Actual data
------       ------      -------            ------
|  1   | ...|   2  | ... |  3  |   ...... |  42   |  
------       ------      -------            ------
   10          20           30                80


// ArrayList <Integer> a = new ArrayList <Integer> (Arrays.asList(1, 2, 3));
------        ------ ------ ------
| 100 | ---> |  10  |  20  |  30  |
------        ------ ------ ------
  a             100    104    108


// ArrayList <Integer> b = new ArrayList <Integer> (a);
------        ------ ------ ------
| 200 | ---> |  10  |  20  |  30  |
------        ------ ------ ------
  b             200    204    208


When you do:

a[1] = 42, it is equivalent to:

------        ------ ------ ------
| 100 | ---> |  10  |  80  |  30  |
------        ------ ------ ------
  a             100    104    108


Note that this does not change b in any way.

Also, take a look at the following code. 另外,请查看以下代码。 Here you can see that it is indeed Shallow Copy because when you modify the value pointed to by the reference, it is reflected in both a and b . 在这里你可以看到它确实是浅层复制,因为当你修改引用指向的值时,它会反映在ab

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;

class Node {

    int data;
    String name;

    Node(int data, String name) {

        this.data = data;
        this.name = name;
    }

    public String toString() {

        return "{" + Integer.toString(data) + ", " + name + "}";
    }
}

class ArrayListTest {

    public static void main(String[] args) {

        ArrayList <Node> a = new ArrayList <Node>();

        Node n[] = new Node[5];
        for(int i = 0; i < 5; i++) {
            n[i] = new Node(i, Integer.toString(i));
        }

        a.add(n[0]);
        a.add(n[1]);
        a.add(n[2]);

        System.out.println("Previously: ");
        System.out.println("a = " + a.toString());

        ArrayList <Node> b = new ArrayList <Node> (a);

        System.out.println("b = " + b.toString());

        // This does not affect b as b has aready made a copy of 
        // all the references in a different location.
        a.add(n[3]);

        n[2].data = 10;
        n[2].name = "10";

        System.out.println("\nCurrent: ");
        System.out.println("a = " + a.toString());
        System.out.println("b = " + b.toString());

    }
}

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

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