Arrays.copyOf()是数组的复制,那么Arrays.copyOf()实现的是深克隆还是浅克隆呢?
我们先来看看什么是深克隆,什么是浅克隆?
首先我们要明确的是,不管是深克隆还是浅克隆,克隆后都会在堆内存空间中开辟一块新地址来存储克隆后的对象,有区别的只是对于原型对象中成员变量是基本数据类型、String类型和引用类型的不同处理
浅克隆
浅克隆(Shadow Clone)是把原型对象中成员变量为值类型的属性都复制给克隆对象,把原型对象中成员变量为引用类型的引用地址也复制给克隆对象,也就是原型对象中如果有成员变量为引用对象,则此引用对象的地址是共享给原型对象和克隆对象的。简单来说就是浅克隆只会复制原型对象,但不会复制它所引用的对象
深克隆
深克隆(Deep Clone)是将原型对象中的所有类型,无论是值类型还是引用类型,都复制一份给克隆对象,也就是说深克隆会把原型对象和原型对象所引用的对象,都复制一份给克隆对象
要想知道数组的Arrays.copyOf()方法实现的是深克隆还是浅克隆,我们先来看看下面的例子:
测试一:int类型的数组
int[] a=new int[]{1,2,3};
int[] b=Arrays.copyOf(a, a.length);
System.out.println(a);
System.out.println(b);
System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(b));
a[0]=10;//修改原型数组的第一个元素值
System.out.println("======================");
System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(b));
输出结果:
[I@19e0bfd
[I@139a55
[1, 2, 3]
[1, 2, 3]
======================
[10, 2, 3]
[1, 2, 3]
由打印结果可以看到:原型数组和克隆出来的数组的地址空间是不一样的,说明数组复制会在堆中开辟新的空间存放数组对象;而修改原型数组中的元素值并不影响复制后的数组,因为数组中存放的元素是int类型;
下面我们通过内存图解来更加形象的理解这个例子:
测试二:String数组
String[] s1=new String[]{"a","b","c"};
String[] s2=Arrays.copyOf(s1, s1.length);
System.out.println(s1);
System.out.println(s2);
System.out.println(Arrays.toString(s1));
System.out.println(Arrays.toString(s2));
s1[0]="hhh";//修改原型数组的第一个元素值
System.out.println("======================");
System.out.println(Arrays.toString(s1));
System.out.println(Arrays.toString(s2));
输出结果:
[Ljava.lang.String;@19e0bfd
[Ljava.lang.String;@139a55
[a, b, c]
[a, b, c]
======================
[hhh, b, c]
[a, b, c]
可以看到,原数组的元素改变依旧对复制的String数组无影响!
测试三:对象数组
public class Person {
private String name;
public Person(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
Person p1=new Person("zhangsan");
Person p2=new Person("lisi");
Person p3=new Person("wangwu");
Person[] person1=new Person[]{p1,p2,p3};
Person[] person2=Arrays.copyOf(person1, person1.length);
System.out.println(person1);
System.out.println(person2);
System.out.println(Arrays.toString(person1));
System.out.println(Arrays.toString(person2));
person1[0].setName("xiaoming");//修改原型数组的第一个元素的属性值
System.out.println("======================");
System.out.println(Arrays.toString(person1));
System.out.println(Arrays.toString(person2));
输出结果:
[Ltest4.Person;@19e0bfd
[Ltest4.Person;@139a55
[Person{name='zhangsan'}, Person{name='lisi'}, Person{name='wangwu'}]
[Person{name='zhangsan'}, Person{name='lisi'}, Person{name='wangwu'}]
======================
[Person{name='xiaoming'}, Person{name='lisi'}, Person{name='wangwu'}]
[Person{name='xiaoming'}, Person{name='lisi'}, Person{name='wangwu'}]
可以看到,当数组元素为对象时,改变原型数组元素的属性会影响到复制数组,说明Arrays.copyOf()只复制对象地址,并没有新创建数组元素!
我们来看看内存图解便一目了然:
可以看到,原型数组和复制后的数组引用变量指向的都是相同的对象,所以对其中一个进行修改,必然也会影响到另一个。
通过上面的几个例子,再回过头去看深克隆和浅克隆的特点,我们就可以大胆的下结论:Arrays.copyOf()实现的是浅克隆
有人可能会问:我们上面的例子中只是修改了数组元素对象的一个属性值,导致原数组的修改影响到了复制数组;那么要是我们修改的是数组元素的整个值呢,会不会也影响到复制数组呢?答案是不会的!
部分代码:
Person p1=new Person("zhangsan");
Person p2=new Person("lisi");
Person p3=new Person("wangwu");
Person[] person1=new Person[]{p1,p2,p3};
Person[] person2=Arrays.copyOf(person1, person1.length);
System.out.println(Arrays.toString(person1));
System.out.println(Arrays.toString(person2));
Person p4=new Person("xiaohong");
person1[0]=p4;//修改原型数组的第一个元素
System.out.println("======================");
System.out.println(Arrays.toString(person1));
System.out.println(Arrays.toString(person2));
输出结果:
[Person{name='zhangsan'}, Person{name='lisi'}, Person{name='wangwu'}]
[Person{name='zhangsan'}, Person{name='lisi'}, Person{name='wangwu'}]
======================
[Person{name='xiaohong'}, Person{name='lisi'}, Person{name='wangwu'}]
[Person{name='zhangsan'}, Person{name='lisi'}, Person{name='wangwu'}]
内存图解: