浅谈克隆

之前对浅克隆、深克隆有一些了解,知道浅克隆意味着这对“双胞胎”持有的对象是同一个,其中一个如果改了持有对象的内容,另一个也会一起被改变。

在刷leetcode的时候,用到了ArrayList的复制,简单的用到了ArrayList.clone()方法进行复制,当时就有疑虑,会不会在改一个list的时候,另一个list的值也被改掉。所以自己做了一些测试

下面是代码

   public static void main(String [] args){
        Dog dog1 = new Dog("happy",5);
        Dog dog2 = new Dog("xiaoming",2);
        Dog dog3 = new Dog("wangcai",3);

        Dog dog4 = new Dog("alibr",5);


        ArrayList list = new ArrayList<>();

        list.add(dog1);
        list.add(dog2);
        list.add(dog3);



        ArrayList list2 = (ArrayList) list.clone();

        list.get(1).setName("huanghuang");

        list.set(0,dog4);

        //Collections.reverse(list2);


        for (int i = 0;i<3;i++){
            System.out.println(list.get(i).getName());
            System.out.println("list2  "+list2.get(i).getName());
        }

    }

Dog类

class Dog{

    String name;
    int age;

    public Dog(String name,int age){
        this.name = name;
        this.age = age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }
}

输出的内容是

alibr
list2  happy
huanghuang
list2  huanghuang
wangcai
list2  wangcai

可以看到
当list用get方法改变[0]号dog的名字时,list2的值也会跟着改变,但是如果用set方法就不会改变list2的值,带着疑惑,查看了一下源码
ArrayList的get方法

    public E get(int index) {
        rangeCheck(index);

        return elementData(index);
    }

ArrayList的set方法

   public E set(int index, E element) {
       rangeCheck(index);

       E oldValue = elementData(index);
       elementData[index] = element;
       return oldValue;
   }

elementData方法

    E elementData(int index) {
        return (E) elementData[index];
    }

看到这觉得get和set方法很相近,为什么结果会不同呢?后来思考了一下,得到答案。
ArrayList.clone()确实是浅克隆,但同时list和list2是两个不同的Arraylist。查看源码也可以看出,这两个list本质上都是elementData这个Object []数组。数组中存放的是对象引用。

大概画一个图


浅谈克隆_第1张图片
屏幕快照 2017-12-25 下午8.32.49.png

这样就一目了然了

当用get方法修改的时候,由于这两个list指向同一个Dog,所以两个的输出都会被修改

但是用set方法,就相当于将list的第一个数组对象指向了另外一个Dog
而此时list2的第一个数组对象仍然是指向第一个Dog
所以这时list2不会被改变。

参考
https://www.cnblogs.com/Qian123/p/5710533.html

你可能感兴趣的:(浅谈克隆)