美文网首页
java中的深复制和浅复制

java中的深复制和浅复制

作者: 这是朕的江山 | 来源:发表于2016-08-08 15:58 被阅读60次

    参考:
    Java如何复制对象

    总结:
    1.我们平常使用的让一个对象等于另外一个对象,如:

    Student a=new Student("A");
    Student b=a;
    

    这个复制其实是对对象引用的复制,复制后a和b都指向了堆中的同一个对象,当b修改时a也会跟着被修改。

    b.setname("B");
    System.out.println(a.name);
    System.out.println(b.name);
    

    以上输出都是B。可以看到复制的对象和原对象之间是互相影响的。

    2.所谓的浅复制,顾名思义就是比较浅的复制,不彻底的复制,当我们浅复制一个对象的时候,我们复制了它的所有的东西,但里面的情况有差别,可以分为两类:
    a.所有实例域和不可变类成员对象,比如八种基本数据类型和String类型,这些东西复制之后,在副本中修改不会影响原对象的这些属性的值
    b.可变成员对象,如Date对象,还是复制它的引用,也就是说副本和原对象之间还是互相影响的。
    举例:

    class Student implements Cloneable{  
        private int number;  
      
        public int getNumber() {  
            return number;  
        }  
      
        public void setNumber(int number) {  
            this.number = number;  
        }  
          
        @Override  
        public Object clone() {  
            Student stu = null;  
            try{  
                stu = (Student)super.clone();  
            }catch(CloneNotSupportedException e) {  
                e.printStackTrace();  
            }  
            return stu;  
        }  
    }  
    public class Test {  
          
        public static void main(String args[]) {  
              
            Student stu1 = new Student();  
            stu1.setNumber(12345);  
            Student stu2 = (Student)stu1.clone();  
              
            System.out.println("学生1:" + stu1.getNumber());  
            System.out.println("学生2:" + stu2.getNumber());  
              
            stu2.setNumber(54321);  
          
            System.out.println("学生1:" + stu1.getNumber());  
            System.out.println("学生2:" + stu2.getNumber());  
        }  
    }  
    

    输出:

    学生1:12345  
    学生2:12345  
    学生1:12345  
    学生2:54321  
    

    这时候我们发现复制1的2修改学号后,1的学号并没有因此而改变,这说明了这些东西都被复制到了一个新的内存空间中。
    又比如:

    class Address  {  
        private String add;  
      
        public String getAdd() {  
            return add;  
        }  
      
        public void setAdd(String add) {  
            this.add = add;  
        }  
          
    }  
      
    class Student implements Cloneable{  
        private int number;  
      
        private Address addr;  
          
        public Address getAddr() {  
            return addr;  
        }  
      
        public void setAddr(Address addr) {  
            this.addr = addr;  
        }  
      
        public int getNumber() {  
            return number;  
        }  
      
        public void setNumber(int number) {  
            this.number = number;  
        }  
          
        @Override  
        public Object clone() {  
            Student stu = null;  
            try{  
                stu = (Student)super.clone();  
            }catch(CloneNotSupportedException e) {  
                e.printStackTrace();  
            }  
            return stu;  
        }  
    }  
    public class Test {  
          
        public static void main(String args[]) {  
              
            Address addr = new Address();  
            addr.setAdd("杭州市");  
            Student stu1 = new Student();  
            stu1.setNumber(123);  
            stu1.setAddr(addr);  
              
            Student stu2 = (Student)stu1.clone();  
              
            System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());  
            System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());  
            addr.setAdd("西湖区");  
      
            System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());  
            System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());  
        }  
    }  
    

    输出:

    学生1:123,地址:杭州市  
    学生2:123,地址:杭州市
    学生1:123,地址:西湖区  
    学生2:123,地址:西湖区   
    

    这时候发现add成员变量是互相影响的,这种复制就不彻底,对象间还有牵连。

    3.所谓的深复制,就是彻底的复制,在浅复制的基础上,使得类中的成员变量复制之后也没有牵连。

    @Override  
        public Object clone() {  
            Student stu = null;  
            try{  
                stu = (Student)super.clone();   //浅复制  
                stu.addr = (Address)addr.clone();   //深度复制  
            }catch(CloneNotSupportedException e) {  
                e.printStackTrace();  
            } 
            return stu;  
        }  
    

    将studen类中的clone方法改成以上就可以了,

    相关文章

      网友评论

          本文标题:java中的深复制和浅复制

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