在Java中浅拷贝?

时间:2019-10-18 14:26:49

标签: java shallow-copy

就像我们将预定义列表传递给新的ArrayList构造函数一样,它将SHALLOW-COPY该列表,这意味着对该列表的引用,因此,如果我们修改新列表,则更改也倾向于在旧列表上进行修改。这个程序不是这种情况....为什么?

public class testArrayList {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);

        List<Integer> list2 = new ArrayList<>(list);

        list.add(3);
        System.out.println(list2.get(2));

    }
}

这给了我无限的例外。为什么?

6 个答案:

答案 0 :(得分:2)

这样做:

List<Integer> list2 = new ArrayList<>(list);

您正在创建列表的副本。这是ArrayList的构造函数代码的简化版本:

public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        // List copy is performed here!
        elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

您想要做的是:

List<Integer> list2 = list1

只需复制参考即可。

答案 1 :(得分:2)

调用该构造函数将创建一个引用相同项目的新列表,但不会由同一列表支持。因此,您可以在不影响旧列表的情况下添加和删除新列表。但是,如果您有一些数据对象,无论您在哪个列表中访问它们,这些对象仍将受到操纵。

答案 2 :(得分:0)

浅表副本意味着它仍将在单独的内存位置中复制列表,但是如果列表中还有其他集合,它将复制对它们的引用,而不是递归复制。这就是为什么会出现边界错误的原因-3仅添加到第一个列表中,而不添加到第二个列表中,因为它们现在作为两个完全独立的列表存在。您正在使用的副本构造函数在the API中描述为:

  

(ArrayList(Collection<? extends E> c):   构造一个包含指定集合元素的列表,其顺序由集合的迭代器返回。

如果您只想复制引用,则可以使用赋值运算符而不是复制构造函数:

List<Integer> list2 = list1;

答案 3 :(得分:0)

List<Integer> list2 = (list);

然后将其添加到列表中,它在list2(即浅拷贝)中起作用,如果您使用Constructor,则就像Deep-copy ...

答案 4 :(得分:0)

来自ArrayList.class

public ArrayList(Collection<? extends E> c) {
        this.elementData = c.toArray();
        if ((this.size = this.elementData.length) != 0) {
            if (this.elementData.getClass() != Object[].class) {
                this.elementData = Arrays.copyOf(this.elementData, this.size, Object[].class);
            }
        } else {
            this.elementData = EMPTY_ELEMENTDATA;
        }

    }

这是实现ArrayList构造函数的方式。复制所有元素,并创建新的ArrayList。如果您想将引用复制到旧列表,则应执行以下操作:

List<Integer> list2 = list;

答案 5 :(得分:-1)

List<Integer> list = new ArrayList<>();
      list.add(1);
      list.add(2);
      List<Integer> list1 = list;
      list1.add(3);
      System.out.println(list1.get(2)
      );