Java 浅拷贝,深拷贝

 本文载自http://blog.youkuaiyun.com/jltxgcy/article/details/35566521

从Java 强引用,软引用,弱引用http://blog.youkuaiyun.com/jltxgcy/article/details/35558465一文中,我们看到把一个对象赋值给另一个对象,本质上是增加了引用计数,但是它们都指向同样的堆内存,它们是一个对象。如果我们想要一个独立的对象,改怎么办呢?答案是clone。

 

1、浅拷贝

     浅拷贝是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象。

      ShallowCopy.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. class Professor0 implements Cloneable {  
  2.     String name;  
  3.     int age;  
  4.    
  5.     Professor0(String name, int age) {  
  6.         this.name = name;  
  7.         this.age = age;  
  8.     }  
  9.    
  10.     public Object clone() throws CloneNotSupportedException {  
  11.         return super.clone();  
  12.     }  
  13. }  
  14.    
  15. class Student0 implements Cloneable {  
  16.     String name;// 常量对象。  
  17.     int age;  
  18.     Professor0 p;// 学生1和学生2的引用值都是一样的。  
  19.    
  20.     Student0(String name, int age, Professor0 p) {  
  21.         this.name = name;  
  22.         this.age = age;  
  23.         this.p = p;  
  24.     }  
  25.    
  26.     public Object clone() {  
  27.         Student0 o = null;  
  28.         try {  
  29.             o = (Student0) super.clone();  
  30.         } catch (CloneNotSupportedException e) {  
  31.             System.out.println(e.toString());  
  32.         }  
  33.    
  34.         return o;  
  35.     }  
  36. }  
  37.    
  38. public class ShallowCopy {  
  39.     public static void main(String[] args) {  
  40.         Professor0 p = new Professor0("wangwu"50);  
  41.         Student0 s1 = new Student0("zhangsan"18, p);  
  42.         Student0 s2 = (Student0) s1.clone();  
  43.         s2.p.name = "lisi";  
  44.         s2.p.age = 30;  
  45.         s2.name = "z";  
  46.         s2.age = 45;  
  47.         System.out.println("学生s1的姓名:" + s1.name + "\n学生s1教授的姓名:" + s1.p.name + "," + "\n学生s1教授的年纪" + s1.p.age);// 学生1的教授  
  48.     }  
  49. }  

      结果:


     s2.p改变了s1.p的内容。而s2.name和s2.age没有改变s1.name和s1.age的内容。


2、深拷贝

     深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. class Professor implements Cloneable {  
  2.     String name;  
  3.     int age;  
  4.    
  5.     Professor(String name, int age) {  
  6.         this.name = name;  
  7.         this.age = age;  
  8.     }  
  9.    
  10.     public Object clone() {  
  11.         Object o = null;  
  12.         try {  
  13.             o = super.clone();  
  14.         } catch (CloneNotSupportedException e) {  
  15.             System.out.println(e.toString());  
  16.         }  
  17.         return o;  
  18.     }  
  19. }  
  20.    
  21. class Student implements Cloneable {  
  22.     String name;  
  23.     int age;  
  24.     Professor p;  
  25.    
  26.     Student(String name, int age, Professor p) {  
  27.         this.name = name;  
  28.         this.age = age;  
  29.         this.p = p;  
  30.     }  
  31.    
  32.     public Object clone() {  
  33.         Student o = null;  
  34.         try {  
  35.             o = (Student) super.clone();  
  36.         } catch (CloneNotSupportedException e) {  
  37.             System.out.println(e.toString());  
  38.         }  
  39.         o.p = (Professor) p.clone();  
  40.         return o;  
  41.     }  
  42. }  
  43.    
  44. public class DeepCopy {  
  45.     public static void main(String args[]) {  
  46.         long t1 = System.currentTimeMillis();  
  47.         Professor p = new Professor("wangwu"50);  
  48.         Student s1 = new Student("zhangsan"18, p);  
  49.         Student s2 = (Student) s1.clone();  
  50.         s2.p.name = "lisi";  
  51.         s2.p.age = 30;  
  52.         System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age);// 学生1的教授不改变。  
  53.         long t2 = System.currentTimeMillis();  
  54.         System.out.println(t2-t1);//耗时  
  55.     }  
  56. }  

     结果:


     s2.p不能改变s1.p的内容。因为是不同对象。


3、当然我们还有一种深拷贝方法,就是将对象串行化:

     但是串行化却很耗时,在一些框架中,我们便可以感受到,它们往往将对象进行串行化后进行传递,耗时较多。

     DeepCopy2.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. import java.io.*;  
  2. //Serialization is time-consuming  
  3. class Professor2 implements Serializable {  
  4.     /** 
  5.      *  
  6.      */  
  7.     private static final long serialVersionUID = 1L;  
  8.     String name;  
  9.     int age;  
  10.    
  11.     Professor2(String name, int age) {  
  12.         this.name = name;  
  13.         this.age = age;  
  14.     }  
  15. }  
  16.    
  17. class Student2 implements Serializable {  
  18.     /** 
  19.      *  
  20.      */  
  21.     private static final long serialVersionUID = 1L;  
  22.     String name;// 常量对象。  
  23.     int age;  
  24.     Professor2 p;// 学生1和学生2的引用值都是一样的。  
  25.    
  26.     Student2(String name, int age, Professor2 p) {  
  27.         this.name = name;  
  28.         this.age = age;  
  29.         this.p = p;  
  30.     }  
  31.    
  32.     public Object deepClone() throws IOException, OptionalDataException,  
  33.             ClassNotFoundException {  
  34.         // 将对象写到流里  
  35.         ByteArrayOutputStream bo = new ByteArrayOutputStream();  
  36.         ObjectOutputStream oo = new ObjectOutputStream(bo);  
  37.         oo.writeObject(this);  
  38.         // 从流里读出来  
  39.         ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());  
  40.         ObjectInputStream oi = new ObjectInputStream(bi);  
  41.         return (oi.readObject());  
  42.     }  
  43.    
  44. }  
  45.    
  46. public class DeepCopy2 {  
  47.    
  48.     /** 
  49.      * @param args 
  50.      */  
  51.     public static void main(String[] args) throws OptionalDataException,  
  52.             IOException, ClassNotFoundException {  
  53.         long t1 = System.currentTimeMillis();  
  54.         Professor2 p = new Professor2("wangwu"50);  
  55.         Student2 s1 = new Student2("zhangsan"18, p);  
  56.         Student2 s2 = (Student2) s1.deepClone();  
  57.         s2.p.name = "lisi";  
  58.         s2.p.age = 30;  
  59.         System.out.println("name=" + s1.p.name + "," + "age=" + s1.p.age); // 学生1的教授不改变。  
  60.         long t2 = System.currentTimeMillis();  
  61.         System.out.println(t2-t1);//耗时  
  62.     }  
  63.    
  64. }  

      结果:


     s2.p不能改变s1.p的内容。因为是不同对象。

     从图中也能看出将对象进行串行化后进行传递,耗时较多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值