Str*_*der 8 java arrays deep-copy shallow-copy
我试图理解Java中浅层和深层复制的概念.关于这个主题有很多文章和问答,但每当我尝试在真正的Java代码中实现这些概念时,我都不清楚一切.
我基于理解的答案之一就是在这个链接中,通过模式解释深度和浅层复制.
我会在每个案例的实施情况下向您展示:
我在我的示例中使用了System.arraycopy()方法,因为我在许多文章中读到它执行浅拷贝(以及克隆方法)
public class Test {
public static void main(String[] args) {
NameValue[] instance1 = {
new NameValue("name1", 1),
new NameValue("name2", 2),
new NameValue("name3", 3),
};
NameValue[] instance2 = new NameValue[instance1.length];
// Print initial state
System.out.println("Arrays before shallow copy:");
System.out.println("Instance 1: " + Arrays.toString(instance1));
System.out.println("Instance 2: " + Arrays.toString(instance2));
// Perform shallow copy
System.arraycopy(instance1, 0, instance2, 0, 3);
// Change instance 1
for (int i = 0; i < 3; i++) {
instance1[i].change();
}
// Print final state
System.out.println("Arrays after shallow copy:");
System.out.println("Instance 1: " + Arrays.toString(instance1));
System.out.println("Instance 2: " + Arrays.toString(instance2));
}
private static class NameValue {
private String name;
private int value;
public NameValue(String name, int value) {
super();
this.name = name;
this.value = value;
}
public void change() {
this.name = this.name + "-bis";
this.value = this.value + 1;
}
@Override
public String toString() {
return this.name + ": " + this.value;
}
}
}
Run Code Online (Sandbox Code Playgroud)
执行主要方法的结果如下:
Arrays before shallow copy:
Instance 1: [name1: 1, name2: 2, name3: 3]
Instance 2: [null, null, null]
Arrays after shallow copy:
Instance 1: [name1-bis: 2, name2-bis: 3, name3-bis: 4]
Instance 2: [name1-bis: 2, name2-bis: 3, name3-bis: 4]
Run Code Online (Sandbox Code Playgroud)
我在这个例子中使用了Arrays.copyOf()方法,因为我在许多文章中读到它执行深层复制(以及Arrays.copyOfRange方法)
public static void main(String[] args) {
NameValue[] instance1 = {
new NameValue("name1", 1),
new NameValue("name2", 2),
new NameValue("name3", 3),
};
NameValue[] instance2 = new NameValue[instance1.length];
// Print initial state
System.out.println("Arrays before deep copy:");
System.out.println("Instance 1: " + Arrays.toString(instance1));
System.out.println("Instance 2: " + Arrays.toString(instance2));
// Perform deep copy
instance2 = Arrays.copyOf(instance1, 3);
// Change instance 1
for (int i = 0; i < 3; i++) {
instance2[i].change();
}
// Print final state
System.out.println("Arrays after deep copy:");
System.out.println("Instance 1: " + Arrays.toString(instance1));
System.out.println("Instance 2: " + Arrays.toString(instance2));
}
Run Code Online (Sandbox Code Playgroud)
显示:
Arrays before deep copy:
Instance 1: [name1: 1, name2: 2, name3: 3]
Instance 2: [null, null, null]
Arrays after deep copy:
Instance 1: [name1-bis: 2, name2-bis: 3, name3-bis: 4]
Instance 2: [name1-bis: 2, name2-bis: 3, name3-bis: 4]
Run Code Online (Sandbox Code Playgroud)
您可能会注意到,main方法的执行结果与上面的模式逻辑不同.
任何解释都将受到欢迎.
我不知道你在哪里阅读copyOf()执行深层复制,因为这是完全错误的.
引用javadoc Arrays.copyOf(T[] original, int newLength):
对于在原始数组和副本中都有效的所有索引,这两个数组将包含相同的值.
这意味着它是一个浅薄的副本.要成为深层副本,值必须指向不同的对象,因为引用的对象也必须是副本.
要执行深层复制,您必须迭代数组并复制值.Java无法为您做到这一点,因为它不知道如何复制对象.
例如,Java如何知道如何复制NameValue对象?clone()?复制构造函数?序列化+反序列化?工厂方法?其他方法?
我试图理解 Java 中浅复制与深复制的概念。
在 Java 中,您传递并存储对对象的引用,而不是对象本身。
因此,当您有一个NameValue[] array数组时,该数组不包含对象NameValue,而是包含对对象的引用。
因此,当您对其进行浅复制时,NameValue[] array2意味着您只是将引用从一个数组复制到另一个数组。这实际上意味着现在 和 都array引用array2完全相同的对象,并且您所做的任何更改都将从(同一对象) array[2]可见。array2[2]
当深度复制时,您将每个对象完全复制到另一个内存区域,并在新数组中保留对该新对象的引用。
这样,两个数组现在引用不同的对象,并且任何更改array[2]都不可见array2[2]
更新:
这不适用于存储实际值而不是引用的基元。
因此,int[] a当您复制时,您会得到值的副本(即某种意义上的深层复制),因为a[2]包含值本身而不是对该值的引用。