下面是自己的总结:
基本概念
* 浅拷贝: 拷贝的是字面量,即数值,即引用(没有创建新的对象,只是将两个引用指向同一对象)
* 深拷贝: 拷贝的是对象! 这个过程中是要新建对象的,想一想对象的复杂程度和完全不可预测的各种可能结构,java api 怎么知道如何将对象拷贝呢,还不是得你自己动手
(emm 关于Object.clone()方法和Cloneable接口 java api 中默认的还是浅拷贝,不过可以自己在类中重写覆盖Object.clone()方法,从而实现深拷贝。详见另一篇博客:弄清Java深浅拷贝问题(二) !Object.clone()方法和Cloneable接口)
javadoc 对于Array.copyOf(T[] original, int newLength) 的描述:
For all indices that are valid in both the original array and the copy, the two arrays will contain identical values.
注意看,描述中说的是“indentical values” ,就是将数组中保存的数值复制粘贴而已。
(1)数组元素是基本数据:因为数组中保存的值就是基本数据本身,所以Array.copyOf相当于新建了一个新的备份,所以可以看作“深拷贝”;
(2)对于数组元素是对象:因为数组中保存的并不是对象本身,而是对象的引用,对象本身是保存在堆上的。所以Array.copyOf只是将引用的值进行复制粘贴,过程中并没有创建新的对象,只是将对应的引用指向相同的对象
示例
(1)数组元素是基本数据(primitive)
(a)浅拷贝:使用“=”
public class ShallowCopy {
public static void main(String[] args) {
int[] a = {1, 2};
int[] b = a;
b[1] = 7;
System.out.println("a[1] = " + a[1]);
}
}
控制台输出: a[1] = 7
(b)深拷贝:for/while 循环一个一个复制;使用Array.copyOf等java api提供的方法
1. 示例1:
使用System.arraycopy
public class CopyArrayByarraycopy {
public static void main(String[] args) {
int[] a = {1, 2, 3, 4};
int[] b = new int[4];
System.arraycopy(a, 0, b, 0, a.length);
b[3] = 7;
System.out.println("Array a:");
for (int i : a)
System.out.print(i + " ");
System.out.println();
System.out.println("Array b:");
for (int j : b)
System.out.print(j + " ");
}
}
输出:
Array a:
1 2 3 4
Array b:
1 2 3 7
2. 示例2:
使用Arrays.copyOf
//导入Arrays类
import java.util.Arrays;
public class CopyArrayByCopyof
{
public static void main(String[] args)
{
int[] a = new int[10];
//copyOf方法
int[] copy = Arrays.copyOf(a, a.length * 2);
//第一个参数为要拷贝的数组名,第二个为拷贝数组的大小(不限定大小,可用于扩大数组,如可以是a.length * 2)
System.out.println(a[1] + " " + copy[2] );
}
}
输出:
0 0
3. 示例3
使用Object.clone
public class CopyArrayByClone {
public static void main(String[] args) {
int[] a = {1, 2, 3, 4};
int[] b = a.clone();
a[0] = 91;
b[1] = 7;
System.out.println("Array a:");
for (int i : a)
System.out.print(i + " ");
System.out.println();
System.out.println("Array b:");
for (int j : b)
System.out.print(j + " ");
}
}
输出:
Array a:
91 2 3 4
Array b:
1 7 3 4
copyOf 和 arraycopy 两者关系如下,可以看到copyOf调用arraycopy:
public static int[] copyOf(int[] original, int newLength) {
int[] copy = new int[newLength];
System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
return copy;
}
(2)浅拷贝:数组元素是对象(object)
代码中使用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;
}
}
}
运行结果显示,只是引用被拷贝了,所以对instance1对象数组的修改会影响instance2对象数组:
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]