zoukankan      html  css  js  c++  java
  • 浅谈java浅拷贝和深拷贝

    前言:深拷贝和浅拷贝的区别是什么? 浅拷贝:被复制的对象的所有变量都含有原来对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之, 浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象。深拷贝:被复制对象的所有变量都含有与原来对象相同的值,而那些引用对象的变量将指向被复制过的新对象,而不再是原有 的那些被引用的对象。换言之,深拷贝把要复制的对象所引用的对象都复制了一遍。

    浅拷贝

      无论是浅拷贝还是深拷贝都要用到clone()方法,所有类都继承于Object,clone方法定义于Object类中但没有实现,

    而如果要使用clone方法,根据源码则必须实现Cloneable接口,java.lang.Cloneable是一个标志性接口不包含任何方法,根据注释clone方法是由C或C++其他本地语言实现的。

      * @return     a clone of this instance.
         * @throws  CloneNotSupportedException  if the object's class does not
         *               support the {@code Cloneable} interface. Subclasses
         *               that override the {@code clone} method can also
         *               throw this exception to indicate that an instance cannot
         *               be cloned.
         * @see java.lang.Cloneable
         */
        protected native Object clone() throws CloneNotSupportedException;

      实现浅拷贝:

    package yunche.test.copy;
    
    /**
     * @ClassName: Dog
     * @Description:
     * @author: yunche
     * @date: 2018/08/25
     */
    public class Dog implements Cloneable
    {
        public String color;
        public int age;
    
        /**
         * 引用变量
         */
        public Erha erha;
    
        public static void main(String[] args) throws CloneNotSupportedException
        {
            Dog d = new Dog();
            d.color="yellow";
            d.age=2;
            d.erha = new Erha();
            d.erha.name = "二哈";
    
            //此时clone方法为浅拷贝
            Dog copyDog = (Dog)d.clone();
            System.out.println(copyDog.color);
            System.out.println(copyDog.age);
            System.out.println(copyDog.erha.name);
    
            //hashcode不同,创建了新对象
            System.out.println(d==copyDog);
            System.out.println(d.hashCode());
            System.out.println(copyDog.hashCode());
    
            //hashcode相同,没有创建新的erha对象,只是复制了引用
            System.out.println(copyDog.erha==d.erha);
            System.out.println(copyDog.erha.hashCode());
            System.out.println(d.erha.hashCode());
    
        }
    
        private static class Erha
        {
             String name;
        }
    }

    深拷贝

      深拷贝对于基本数据类型进行值传递,对引用数据类型,创建一个新的对象。并复制其内容。怎么实现深拷贝呢?通常的方案有两种:1.序列化这个对象,再反序列化回来,就可以得到这个新的对象,序列化的规则需要我们自己来写。2.重写clone方法,我们可以对其内部引用类型的变量,再进行一次clone()。

     序列化方式

     序列化需要实现Serializable接口。

    package yunche.test.copy;
    
    import java.io.*;
    
    /**
     * @ClassName: Dog
     * @Description:
     * @author: yunche
     * @date: 2018/08/25
     */
    public class Dog implements Cloneable, Serializable
    {
        public String color;
        public int age;
    
        /**
         * 引用变量
         */
        public Erha erha;
    
        public static void main(String[] args) throws CloneNotSupportedException
        {
            Dog d = new Dog();
            d.color="yellow";
            d.age=2;
            d.erha = new Erha();
            d.erha.name = "二哈";
    
            
            Dog copyDog = (Dog)d.deepClone();
            System.out.println(copyDog.color);
            System.out.println(copyDog.age);
            System.out.println(copyDog.erha.name);
    
            //hashcode不同,创建了新对象
            System.out.println(d==copyDog);
            System.out.println(d.hashCode());
            System.out.println(copyDog.hashCode());
    
            //hashcode不同,创建新的erha对象,实现了深拷贝
            System.out.println(copyDog.erha==d.erha);
            System.out.println(copyDog.erha.hashCode());
            System.out.println(d.erha.hashCode());
    
        }
    
        public Object deepClone()
        {
            File f = new File("dog.obj");
            Object obj =null;
            try(FileOutputStream fos = new FileOutputStream(f);
                ObjectOutputStream oos = new ObjectOutputStream(fos);
                FileInputStream fis = new FileInputStream(f);
                ObjectInputStream ois = new ObjectInputStream(fis))
            {
                oos.writeObject(this);
                obj = ois.readObject();
            }
            catch (FileNotFoundException e)
            {
                e.printStackTrace();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            catch (ClassNotFoundException e)
            {
                e.printStackTrace();
            }
            return obj;
        }
    
        private static class Erha implements Serializable
        {
             String name;
        }
    }

     重写clone

    package yunche.test.copy;
    
    import java.io.*;
    
    /**
     * @ClassName: Dog
     * @Description:
     * @author: yunche
     * @date: 2018/08/25
     */
    public class Dog implements Cloneable
    {
        public String color;
        public int age;
    
        /**
         * 引用变量
         */
        public Erha erha;
    
        public static void main(String[] args) throws CloneNotSupportedException
        {
            Dog d = new Dog();
            d.color="yellow";
            d.age=2;
            d.erha = new Erha();
            d.erha.name = "二哈";
    
            //重新clone方法,实现深拷贝
            Dog copyDog = (Dog)d.clone();
            System.out.println(copyDog.color);
            System.out.println(copyDog.age);
            System.out.println(copyDog.erha.name);
    
            //hashcode不同,创建了新对象
            System.out.println(d==copyDog);
            System.out.println(d.hashCode());
            System.out.println(copyDog.hashCode());
    
            //hashcode不同,创建新的erha对象,实现了深拷贝
            System.out.println(copyDog.erha==d.erha);
            System.out.println(copyDog.erha.hashCode());
            System.out.println(d.erha.hashCode());
    
        }
    
        @Override
        public Object clone()
        {
            try
            {
                Dog dog = (Dog)super.clone();
                dog.erha = (Erha) this.erha.clone();
                return dog;
    
            }
            catch (CloneNotSupportedException e)
            {
                e.printStackTrace();
            }
            return null;
        }
    
        public static class Erha implements Cloneable
        {
             String name;
    
             @Override
             public Object clone()
             {
                 try
                 {
                     return super.clone();
                 }
                 catch (CloneNotSupportedException e)
                 {
                     e.printStackTrace();
                 }
                 return null;
             }
        }
    }

    参考资料

      https://segmentfault.com/a/1190000010648514

  • 相关阅读:
    hdu6229 Wandering Robots 2017沈阳区域赛M题 思维加map
    hdu6223 Infinite Fraction Path 2017沈阳区域赛G题 bfs加剪枝(好题)
    hdu6438 Buy and Resell 买卖物品 ccpc网络赛 贪心
    hdu6441 Find Integer 求勾股数 费马大定理
    bzoj 1176 Mokia
    luogu 3415 祭坛
    bzoj 1010 玩具装箱
    bzoj 3312 No Change
    luogu 3383【模板】线性筛素数
    bzoj 1067 降雨量
  • 原文地址:https://www.cnblogs.com/yunche/p/9534200.html
Copyright © 2011-2022 走看看