• 深拷贝、浅拷贝与Cloneable接口


    深拷贝与浅拷贝

    浅拷贝

    public class Student implements Cloneable{
        Integer a;
        Integer b;
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    
        String c;
        Student child;
    }
    
    public class Main {
    
        public static void main(String[] args) throws CloneNotSupportedException {
            Student s = new Student();
            Student s2 = (Student) s.clone();
            System.out.println(s == s2);
            System.out.println(s.child == s2.child);
        }
    }
    /**********************************************************************/
    false
    true
    

    由上述代码及运行结果我们可以看出,调用clone方法之后,确实s2是一个新的对象,内存地址已经发生了改变,但s和s2的child属性仍然指向相同的地址,这便是浅拷贝,当然8种基本数据类型是深拷贝,String则是例外。

    深拷贝

    public class Teacher implements Cloneable{
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
    
    
    public class Student implements Cloneable{
        Integer a;
        Integer b;
    
        public Student(Teacher t) {
            this.t = t;
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            Student s = (Student) super.clone();
            s.t = (Teacher)s.t.clone();//彻底深拷贝关键
            return s;
        }
    
        String c;
        Teacher t;
    }
    
    
    public class IntersectionofTwoArraysII {
    
        public static void main(String[] args) throws CloneNotSupportedException {
            Teacher t = new Teacher();
            Student s = new Student(t);
            Student s2 = (Student) s.clone();
            System.out.println(s == s2);
            System.out.println(s.t == s2.t);
        }
    }
    /**********************************************************************/
    false
    false
    

    如上代码运行结果所示为深拷贝,想要实现深拷贝,就需要在重写Cloneable接口的clone()方法,并调用属性的clone()方法,因此关联类也要实现Cloneable接口,从而形成拷贝链,实现彻底深拷贝
    实现彻底的深拷贝并不容易,因为它要求涉及的所有类都实现了cloneable接口,但是如StringBuffer由于其没有实现Cloneable接口,想要实现深拷贝效果,则需要做特殊处理从而实现深拷贝的效果。可以在clone方法中实现
    sb=new StringBuffer(sb.toString());

    Cloneable接口

    Cloneable其实就是一个标记接口,只有实现这个接口后,然后在类中重写Object中的clone方法,然后通过类调用clone方法才能克隆成功,如果不实现Cloneable其实就是一个标记接口接口,调用clone方法则会抛出CloneNotSupportedException(克隆不被支持)异常。

    如何判断类是否实现了cloneable接口呢?

    /**
         * Creates and returns a copy of this {@code Object}. The default
         * implementation returns a so-called "shallow" copy: It creates a new
         * instance of the same class and then copies the field values (including
         * object references) from this instance to the new instance. A "deep" copy,
         * in contrast, would also recursively clone nested objects. A subclass that
         * needs to implement this kind of cloning should call {@code super.clone()}
         * to create the new instance and then create deep copies of the nested,
         * mutable objects.
         *
         * @return a copy of this object.
         * @throws CloneNotSupportedException
         *             if this object's class does not implement the {@code
         *             Cloneable} interface.
         */
        protected Object clone() throws CloneNotSupportedException {
            if (!(this instanceof Cloneable)) {
                throw new CloneNotSupportedException("Class doesn't implement Cloneable");
            }
     
            return internalClone((Cloneable) this);
        }
     
        /*
         * Native helper method for cloning.
         */
        private native Object internalClone(Cloneable o);
    

    clone方法首先会判对象是否实现了Cloneable接口,若无则抛出CloneNotSupportedException, 最后会调用internalClone. intervalClone是一个native方法,一般来说native方法的执行效率高于非native方法。

    参考资料

    详解Java中的clone方法 -- 原型模式

  • 相关阅读:
    出现System.web.mvc冲突的原因及解决方法CS0433
    看完此文还不懂NB-IoT,你就过来掐死我吧...
    html5调用手机陀螺仪实现方向辨识
    黑盒测试和白盒测试的区别
    CentOS7 下 keepalived 的安装和配置
    centos 下 mysql+keepalived实现双主自由切换
    MySQL 高可用性—keepalived+mysql双主(有详细步骤和全部配置项解释)
    备份VMware虚拟磁盘文件 移植到其他虚拟机
    Centos7 Mysql 双机热备实现数据库高可用
    CentOS7配置Mysql热备份
  • 原文地址:https://www.cnblogs.com/wunsiang/p/12812723.html
Copyright © 2020-2023  润新知