zoukankan      html  css  js  c++  java
  • 深拷贝、浅拷贝与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方法 -- 原型模式

  • 相关阅读:
    uva 147 Dollars
    hdu 2069 Coin Change(完全背包)
    hdu 1708 Fibonacci String
    hdu 1568 Fibonacci
    hdu 1316 How Many Fibs?
    poj 1958 Strange Towers of Hanoi
    poj 3601Tower of Hanoi
    poj 3572 Hanoi Tower
    poj 1920 Towers of Hanoi
    筛选法——素数打表
  • 原文地址:https://www.cnblogs.com/wunsiang/p/12812723.html
Copyright © 2011-2022 走看看