zoukankan      html  css  js  c++  java
  • JAVA SE之Cloneable 深拷贝和浅拷贝的区别

    对照下面的例子很容易看出:
    当一个对象赋值给另一个对象变量时,是相同的引用,公用这个对象实例;
    浅拷贝,需要实现Cloneable这个标记接口,然后自行实现clone方法,clone方法的默认就是浅拷贝;注意:当对象中成员变量都是基本类型或者不可变量如String的时候,浅拷贝是安全的。
    但是当变量中存在子对象变量的引用时,就需要深拷贝了,因为浅拷贝并不会对子对象进行clone,这样就造成子对象变为共享域,对象和对象副本都会造成它的状态等改变。因此,深拷贝就类似于递归的把对象本身及对象中包含的对象都进行clone。

    package learning.copy;
    
    /**
     *@className SuperficialCopy
     *@description :浅拷贝,当对象本身不含有子对象引用的时候,浅拷贝是安全的    
     *                  clone方法的默认就是浅拷贝,深拷贝需要自己去实现。
     *@author Wanggd @date 2017年5月27日上午11:20:23
     */
    public class SuperficialCopy implements Cloneable{
    
        String name;
        int age;
    
        SuperficialCopy(String name,int age){
            this.age = age;
            this.name = name;
        }
    
        @Override
        public Object clone() throws CloneNotSupportedException{
    
            Object o = super.clone();
            return o;
        }
    
        public static void main(String[] args) throws CloneNotSupportedException {
            SuperficialCopy obj1 = new SuperficialCopy("Kevin",20);
    
            SuperficialCopy copyObj = (SuperficialCopy) obj1.clone();
            copyObj.age = 80;
            System.out.println("object1's age = " + obj1.age );
            //结果:object1's age = 20
    
            SuperficialCopy obj2 = obj1;
            obj2.age = 90;
            System.out.println("changed by obj2 object1's age = " + obj1.age );
            //changed by obj2 object1's age = 90
        }
    
    }
    
    package learning.copy;
    
    /**
     *@className SuperficialCopyHasObj
     *@description :浅拷贝,当浅拷贝发生在对象含有子对象引用的时候,浅拷贝就不再是安全的。 
     *@author Wanggd @date 2017年5月27日上午11:21:48
     *
     */
    public class SuperficialCopyHasObj implements Cloneable{
    
        private String name;
        private int age;
        private Inner inner;
    
        SuperficialCopyHasObj(String name,int age,Inner inner){
            this.age = age;
            this.name = name;
            this.inner = inner;
        }
    
        @Override
        public Object clone() throws CloneNotSupportedException{
    
            Object o = super.clone();
            return o;
        }
    
        public static void main(String[] args) throws CloneNotSupportedException {
            SuperficialCopyHasObj obj1 = new SuperficialCopyHasObj("Kevin",20,new Inner("who",66));
            System.out.println("Before object1's inner name = " + obj1.inner.getInnerName() );
            //结果:Before object1's inner name = who
    
            SuperficialCopyHasObj copyObj = (SuperficialCopyHasObj) obj1.clone();
            copyObj.age = 80;
            System.out.println("object1's age = " + obj1.age );
            //结果:object1's age = 20
    
            copyObj.inner.setInnerName("what");
            System.out.println("object1's inner name = " + obj1.inner.getInnerName() );
            //object1's inner name = what
    
        }
    
    }
    
    package learning.copy;
    
    /**
     *@className DeepCopy
     *@description :深度拷贝,对象本身及包含的对象引用也要clone    
     *@author Wanggd @date 2017年5月27日上午11:19:23
     */
    public class DeepCopy implements Cloneable{
        private String name;
        private int age;
        private Inner inner;
    
        DeepCopy(String name, int age, Inner inner){
            this.name = name;
            this.age = age;
            this.inner = inner;
        }
    
        public Object clone(){
            DeepCopy o = null;
            try {
                o = (DeepCopy)super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            o.inner = (Inner)inner.clone();
            return o;
        }
    
        public static void main(String[] args) {
            Inner inner = new Inner("I'm inner",10);
            DeepCopy obj1 = new DeepCopy("I'm kevin", 20, inner);
    
            DeepCopy copyObj = (DeepCopy) obj1.clone();
            copyObj.setAge(88);
            copyObj.inner.setInnerAge(90);
            copyObj.inner.setInnerName("changes");
    
            System.out.println("obj1's age=" + obj1.age + ",obj1's inner name=" + obj1.inner.getInnerName());
            //结果:obj1's age=20,obj1's inner name=I'm inner
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public Inner getInner() {
            return inner;
        }
    
        public void setInner(Inner inner) {
            this.inner = inner;
        }
    
    
    }
    
    class Inner implements Cloneable{
    
        private String innerName;
        private int innerAge;
    
        Inner(String innerName, int innerAge){
            this.innerAge = innerAge;
            this.innerName = innerName;
        }
    
        public String getInnerName() {
            return innerName;
        }
    
        public void setInnerName(String innerName) {
            this.innerName = innerName;
        }
    
        public int getInnerAge() {
            return innerAge;
        }
    
        public void setInnerAge(int innerAge) {
            this.innerAge = innerAge;
        }
    
        public Object clone(){
            Object o = null;
            try {
                o = super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return o;
        }
    
    }
  • 相关阅读:
    第六周学习心得
    syncnavigator关于win10、win8系统无法注册机进行激活的问题
    使用SyncNavigator轻松实现数据库异地同步、断点续传、异构同步
    数据库同步的正确打开方式
    使用SyncNavigator实现数据库异地同步。
    聊聊MySQL主从数据库同步的那些事儿
    高并发架构系列:数据库主从同步的3种一致性方案实现,及优劣比较
    MySQL binlog数据库同步技术总结
    数据库同步的两种方式
    某省肿瘤医院 — 数据备份 + 数据库同步
  • 原文地址:https://www.cnblogs.com/Kevin-1992/p/12608433.html
Copyright © 2011-2022 走看看