11

我要上最后一节课NameAndValue。我NameAndValue使用复制了一个对象数组,System.arrayCopy()当我更改NameAndValue复制数组中的对象时,它会反映在原始数组中。

public final class NameAndValue {
    public String name;
    public String value;

    public NameAndValue() { }

    public NameAndValue(String name, String value) {
        this.name = name;
        this.value = value;
    }
}
public class Main {
    public static void main(String[] args) {
        NameAndValue[] nv = new NameAndValue[4];
        nv[0] = new NameAndValue("A", "1");
        nv[1] = new NameAndValue("B", "2");
        nv[2] = new NameAndValue("C", "3");
        nv[3] = new NameAndValue("D", "4");

        NameAndValue[] nv2 = new NameAndValue[4];
        System.arraycopy(nv, 0, nv2, 0, 2);
        nv2[2] = new NameAndValue("Y", "25");
        nv2[3] = new NameAndValue("Z", "26");

        for (int i = 0; i < 2; i++) {
            NameAndValue[] nv3 = new NameAndValue[4];
            System.arraycopy(nv2, 0, nv3, 0, 4);
            nv3[2].value = String.valueOf(i);
            nv3[3].value = String.valueOf(i + 1);

            System.out.println(nv2[2].value);
            System.out.println(nv2[3].value);
            System.out.println("-----------------------");
        }
    }
}

我得到的输出为:

0
1
-----------------------
1
2
-----------------------

在所有情况下,我都应该得到 25 和 26 的输出,对吗?为什么会变??

4

6 回答 6

22

System.arrayCopy() 复制对象或对对象的引用?

参考,是拷贝。令人惊讶的是,文档并没有明确地说,只是隐含地说,因为他们谈论复制数组元素,而不是递归地复制他们引用的东西。

就像你有这个一样:

NameAndValue nv1 = new NameAndValue("A", "1");
NameAndValue nv2 = nv1;
nv2.value = "4";
System.out.println(nv1.value); // 4

每个数组元素就像上面的nv1and nv2vars。正如nv1nv2引用(指向)相同的底层对象一样,数组条目也是如此,包括这些条目从一个数组复制到另一个数组时。

于 2013-02-28T12:06:00.667 回答
2

它会发生变化,因为两个数组仍然引用相同的底层对象。您可以将一个新对象分配给数组中的某个位置,并且它不会反映在另一个数组中,但是如果您对两个数组都指向的对象进行修改,那么两者都会以不同的方式看到它。

从这个意义上说,它是“按值引用”传递,而不是严格按引用传递 - 但您看到的效果是因为引用保持不变。

除非另有明确说明,否则像这样的副本在 Java 中几乎总是浅副本。这也不例外。

于 2013-02-28T12:05:13.040 回答
1

据我所知arraycopy是浅拷贝。这意味着新数组将引用旧数组中元素的地址。因此,如果您在其中一个中调整一个值,它将反映在两者中

于 2013-02-28T12:09:00.677 回答
1

System.arraycopy 是一个浅拷贝。原因如下:

它使用 JNI 来使用类似 memcpy() 的东西,它只是复制内存中的指针。这是一个非常快速的操作。

于 2013-12-03T20:31:40.937 回答
0
int[] a = {1, 2, 3};
int[] b = new int[3];
System.arraycopy(a, 0, b, 0, 3);
b[1] = 0;
System.out.println(Arrays.toString(b));
System.out.println(Arrays.toString(a));

输出是这样的:

[1, 0, 3]
[1, 2, 3]
于 2016-08-12T02:44:29.477 回答
0

MethodSystem.arraycopy不执行数组的深拷贝Arrays.copyOf, method 也不执行。它复制对对象的引用并且不创建新实例。如果您修改其中一个数组中的任何对象,它会影响两个数组:

public static void main(String[] args) {
    NameAndValue[] arr1 = new NameAndValue[2];
    arr1[0] = new NameAndValue("A", "1");
    arr1[1] = new NameAndValue("B", "2");

    NameAndValue[] arr2 = new NameAndValue[2];
    System.arraycopy(arr1, 0, arr2, 0, 2);
    arr2[0].value = "3";                       // modify existing object

    NameAndValue[] arr3 = new NameAndValue[2];
    System.arraycopy(arr1, 0, arr3, 0, 2);
    arr3[1] = new NameAndValue("Y", "5");      // create new instance

    System.out.println(Arrays.toString(arr1)); // [A:3, B:2]
    System.out.println(Arrays.toString(arr2)); // [A:3, B:2]
    System.out.println(Arrays.toString(arr3)); // [A:3, Y:5]
}
public static final class NameAndValue {
    public String name;
    public String value;

    public NameAndValue(String name, String value) {
        this.name = name;
        this.value = value;
    }

    @Override
    public String toString() {
        return name + ":" + value;
    }
}

另请参阅:
为什么 Array.copyOf() 在 2D 数组的情况下会改变原始数组?
如何在Java 中进行二维数组的深拷贝?

于 2021-01-01T05:23:38.547 回答