今天在学习《Head First 设计模式》模板方法模式一章中,阅读到了数组的sort()方法的源码,其中使用了clone()对数组进行了一份复制,再对其进行排序。之前没有接触过clone()方法,今天查阅资料,了解了Java中的浅拷贝与深拷贝的概念,简单谈谈自己的理解。

概念

  • 浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对主对象进行拷贝,但不会复制主对象里面的对象。里面的对象会在原来的对象和它的副本之间共享。即,若对象中的属性是基本类型,拷贝的就是基本类型的值;若对象中的属性是引用类型,则拷贝它的内存地址,故拷贝对象与被拷贝对象两者对该引用类型的修改,都会对彼此所持有的该属性有影响。
  • 深拷贝:深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。即当对象和它所引用的对象一起拷贝时为深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。

实现

实现了Cloneable接口的类具有可以被拷贝的功能,同时,需要重写clone()方法。

  • 浅拷贝实现:
    1
    2
    3
    4
    5
    6
    7
    8
    @Override
    public Object clone() {
    try {
    return super.clone(); // 直接调用父类的clone()方法
    } catch (CloneNotSupportedException e) {
    return null;
    }
    }
  • 深拷贝实现:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /**
    * 假如Student类实现了Cloneable接口,且持有一个Teacher对象
    */

    @Override
    public Object clone() {
    Student student = (Student) super.clone(); // 先进行浅拷贝拷贝所有非引用类型的属性
    student.setTeacher((Teacher) student.getTeacher().clone()); // 再将所持有的引用类型(Teacher对象)进行一次浅拷贝,并赋值给拷贝对象所持有的引用类型属性
    return student; // 此时返回的拷贝对象,就持有了一个具有被拷贝对象相同引用类型属性的对象,且拷贝对象持有的该对象与被拷贝对象持有的对象不是同一个对象(内存地址不同)
    }