JAVA 深复制与浅复制


一、引言
   对象拷贝(Object Copy)就是将一个对象的属性拷贝到另一个有着相同类类型的对象中去。在程序中拷贝对象是很常见的,主要是为了在新的上下文环境中复用对象的部分或全部 数据。Java中有三种类型的对象拷贝:浅拷贝(Shallow Copy)、深拷贝(Deep Copy)、延迟拷贝(Lazy Copy)。

二、浅拷贝

1、什么是浅拷贝
   浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。


  在图中,SourceObject有一个int类型的属性 "field1"和一个引用类型属性"refObj"(引用ContainedObject类型的对象)。当对SourceObject做浅拷贝时,创建了CopiedObject,它有一个包含"field1"拷贝值的属性"field2"以及仍指向refObj本身的引用。由于"field1"是基本类型,所以只是将它的值拷贝给"field2",但是由于"refObj"是一个引用类型, 所以CopiedObject指向"refObj"相同的地址。因此对SourceObject中的"refObj"所做的任何改变都会影响到CopiedObject。

2、用例:

public class Subject {
    private String name; 
   public Subject(String s) { 
      name = s; 
   } 
   public String getName() { 
      return name; 
   } 
   public void setName(String s) { 
      name = s; 
   } 
}
public class Student implements Cloneable { 
    // 对象引用 
   private Subject subj; 

   private String name; 

   public Student(String s, String sub) { 
      name = s; 
      subj = new Subject(sub); 
   } 

   public Subject getSubj() { 
      return subj; 
   } 

   public String getName() { 
      return name; 
   } 

   public void setName(String s) { 
      name = s; 
   } 

   /** 
    *  重写clone()方法 
    * @return 
    */ 
   public Object clone() { 
      //浅拷贝 
      try { 
         // 直接调用父类的clone()方法
         return super.clone(); 
      } catch (CloneNotSupportedException e) { 
         return null; 
      } 
   } 
}
public class CopyTest {
    public static void main(String[] args) {
        // 原始对象
        Student stud = new Student("John", "Algebra");
        System.out.println("Original Object: " + stud.getName() + " - " + stud.getSubj().getName());
        // 拷贝对象
        Student clonedStud = (Student) stud.clone();
        System.out.println("Cloned Object: " + clonedStud.getName() + " - " + clonedStud.getSubj().getName());
        // 原始对象和拷贝对象是否一样:
        System.out.println("Is Original Object the same with Cloned Object: " + (stud == clonedStud));
        // 原始对象和拷贝对象的name属性是否一样
        System.out.println("Is Original Object's field name the same with Cloned Object: " +
     (stud.getName() == clonedStud.getName()));
        // 原始对象和拷贝对象的subj属性是否一样
        System.out.println("Is Original Object's field subj the same with Cloned Object: " +
    (stud.getSubj() == clonedStud.getSubj()));
        stud.setName("Dan");
        stud.getSubj().setName("Physics");
        System.out.println("Original Object after it is updated: " + stud.getName() + " - " +
     stud.getSubj().getName());
        System.out.println("Cloned Object after updating original object: " + clonedStud.getName() +
     " - " + clonedStud.getSubj().getName());
    }
}
结果:

 Original Object: John - Algebra
 Cloned Object: John - Algebra
 Is Original Object the same with Cloned Object: false
 Is Original Object's field name the same with Cloned Object: true
 Is Original Object's field subj the same with Cloned Object: true
 Original Object after it is updated: Dan - Physics
 Cloned Object after updating original object: John - Physics

三、深拷贝
1、什么是深拷贝
   深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。



在上图中,SourceObject有一个int类型的属性 "field1"和一个引用类型属性"refObj1"(引用ContainedObject类型的对象)。当对SourceObject做深拷贝时,创建了CopiedObject,它有一个包含"field1"拷贝值的属性"field2"以及包含"refObj1"拷贝值的引用类型属性"refObj2" 。因此对SourceObject中的"refObj"所做的任何改变都不会影响到CopiedObject

2、用例:(在浅复制的基础上修改)

public class Student implements Cloneable { 
   // 对象引用 
   private Subject subj; 

   private String name; 

   public Student(String s, String sub) { 
      name = s; 
      subj = new Subject(sub); 
   } 

   public Subject getSubj() { 
      return subj; 
   } 

   public String getName() { 
      return name; 
   } 

   public void setName(String s) { 
      name = s; 
   } 

   /** 
    * 重写clone()方法 
    * 
    * @return 
    */ 
   public Object clone() { 
      // 深拷贝,创建拷贝类的一个新对象,这样就和原始对象相互独立
      Student s = new Student(name, subj.getName()); 
      return s; 
   } 
}

结果:

 Original Object: John - Algebra
 Cloned Object: John - Algebra
 Is Original Object the same with Cloned Object: false
 Is Original Object's field name the same with Cloned Object: true
 Is Original Object's field subj the same with Cloned Object: false
 Original Object after it is updated: Dan - Physics
 Cloned Object after updating original object: John - Algebra


四、延迟拷贝
   延迟拷贝是浅拷贝和深拷贝的一个组合,实际上很少会使用。 当最开始拷贝一个对象时,会使用速度较快的浅拷贝,还会使用一个计数器来记录有多少对象共享这个数据。当程序想要修改原始的对象时,它会决定数据是否被共享(通过检查计数器)并根据需要进行深拷贝。 
   延迟拷贝从外面看起来就是深拷贝,但是只要有可能它就会利用浅拷贝的速度。当原始对象中的引用不经常改变的时候可以使用延迟拷贝。由于存在计数器,效率下降很高,但只是常量级的开销。而且, 在某些情况下, 循环引用会导致一些问题。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值