深浅克隆之Arrays.copyOf()

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'}]

内存图解:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/can_chen/article/details/105571581