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



我长期以来一直与Java的容器的复制构造函数混淆,是浅复制还是深副本?以下是我的理解:ints1,ints2,ints3是参考文献,因此它们位于堆栈中。Inst1指向堆中的某个对象,并且该对象包含三个匿名引用,它们位于堆栈中,它们指向具有int值0、1、2的对象。

ints2 = ints1

因此,ints2指向与ints1相同的对象。因此。

ints2.set(1,0+10)

将更改Refenence ints1.get(0)的对象。

ints3 = new ArrayList<>(ints1)

接下来是我的困惑。

如果复制构造函数是浅副本,则尽管ints1和ints3指向不同的对象,但两个对象具有相同的引用!因此,通过操纵ints1中的参考来更改对象的任何动作都会更改ints3,因为它们指向相同的对象。

如果复制构造函数是深拷贝,则INTS1和INTS3将保存不同的引用并指向不同的对象。那么INTS1的变化将不会影响INTS3中的变化。

根据结果,复制构造函数似乎是深副本,而不是浅副本。

希望有人能纠正我,谢谢

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]

答案是:浅副本。请看一下这篇文章,其中提供了有关该主题的更多详细信息:http://javarevisited.blogspot.co.uk/2014/03/how-to-clone-collection-collection-in-collection-in-java-in-java-deep-copy-vs-nallow。html?m = 1

问题的关键是,当您进行ints3.set(1, 1+10)时,您实际上正在更改ints3[1]中存储的参考。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.

另外,请查看以下代码。在这里,您可以看到它确实是浅副本,因为当您修改参考指向的值时,它会反映在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());
    }
}

最新更新