美文网首页
浅谈克隆

浅谈克隆

作者: 西元前__YP | 来源:发表于2017-12-25 20:45 被阅读0次

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

    在刷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<Dog> list = new ArrayList<>();
    
            list.add(dog1);
            list.add(dog2);
            list.add(dog3);
    
    
    
            ArrayList<Dog> list2 = (ArrayList<Dog>) 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 []数组。数组中存放的是对象引用。

    大概画一个图


    屏幕快照 2017-12-25 下午8.32.49.png

    这样就一目了然了

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

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

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

    相关文章

      网友评论

          本文标题:浅谈克隆

          本文链接:https://www.haomeiwen.com/subject/qedrgxtx.html