java 中的浅拷贝?

Shallow copy in java?

就好像我们将预定义列表传递给新的 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));

    }
}

它给了我越界异常.. 为什么?

通过做:

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

这只是复制引用。

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

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

(ArrayList(Collection<? extends E> c): Constructs a list containing the elements of the specified collection, in the order they are returned by the collection's iterator.

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

List<Integer> list2 = list1;
List<Integer> list2 = (list);

然后添加到list中,作用在list2中,也就是Shallow-Copy,如果用Constructor,就相当于Deep-copy...

来自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;