java中的clone机制及序列化 java中的clone机制及序列化

    在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也就是说,AB是两个独立的对象,但B的初始值是由A对象确定的。在这种情况下常常使用clone。当然你完全可以new一个新的,让后再进行赋值。但应用clone会有如下的好处:

     1、实现clone方法比较简单、方便。

     2、Object类的clone()一个native方法,native方法的效率一般来说都是远高于java中的非native方法,因此clone方法是高效的。

    注意;通过序列化的方式也可以实现clone。如果一个对象包含复杂类型的变量时,可用序列化或深度clone来实现对象的clone。

 

浅度复制和深度复制

  
    在java中,对于基本类型的数据可采用浅度复制的方式进行对象的复制,其中做法就是直接继承Cloneable接口,调用Object类的clone()方法就可以了。而对于非基本类型的数据,复制方法只能采用深度复制或序列化的方式进行复制。
    典型的实例:
Java代码    收藏代码
  1. /** 
  2.  *  
  3.  * @功能   羊对象类   
  4.  * @创建人   gao_jie 
  5.  * @创建日期 Jun 25, 2009 
  6.  * @版本     1.0 
  7.  *  
  8.  */  
  9. public class Sheep implements Cloneable {  
  10.       
  11.     private String name;//名字  
  12.   
  13.     public String getName() {  
  14.         return name;  
  15.     }  
  16.   
  17.     public void setName(String name) {  
  18.         this.name = name;  
  19.     }  
  20.       
  21.     /* (non-Javadoc) 
  22.      * @see java.lang.Object#clone() 
  23.      */  
  24.     public Object clone() throws CloneNotSupportedException {  
  25.         return super.clone();  
  26.     }  
  27. }  
  28.   
  29. public class Sheepfold implements Cloneable {  
  30.      public Sheep sheep;//羊对象  
  31.      public String name;//羊圈名字  
  32.      public int number;//数量  
  33.   
  34.      public Sheepfold() {  
  35.          this.sheep = new Sheep();  
  36.      }  
  37.     /* (non-Javadoc) 
  38.      * @see java.lang.Object#clone() 
  39.      */  
  40.     public Object clone() throws CloneNotSupportedException {  
  41.         return super.clone();  
  42.     }  
  43. }  
  44.   
  45. public class Test {  
  46.     public static void main(String[] args) {  
  47.         // 声明一个小羊圈对象  
  48.         Sheepfold smallFold = new Sheepfold();  
  49.         smallFold.name = "小羊圈";  
  50.         smallFold.number = 10;  
  51.         smallFold.sheep.setName("小羊");  
  52.         // 复制羊圈  
  53.         Sheepfold bigFold = null;  
  54.         try {  
  55.             bigFold = (Sheepfold) smallFold.clone();  
  56.         } catch (CloneNotSupportedException e) {  
  57.             // TODO Auto-generated catch block  
  58.             e.printStackTrace();  
  59.         }  
  60.         bigFold.name="大羊圈";  
  61.         bigFold.number=100;  
  62.         bigFold.sheep.setName("大羊");  
  63.           
  64.         System.out.println("小羊圈输出信息如下:");  
  65.         System.out.println("smallFold.name="+smallFold.name);  
  66.         System.out.println("smallFold.number="+smallFold.number);  
  67.         System.out.println("smallFold.sheep="+smallFold.sheep.getName());  
  68.         System.out.println("大羊圈输出信息如下:");  
  69.         System.out.println("bigFold.name="+bigFold.name);  
  70.         System.out.println("bigFold.number="+bigFold.number);  
  71.         System.out.println("bigFold.sheep="+bigFold.sheep.getName());  
  72.     }  
  73. }  
  74. 测试结果:  
  75. 小羊圈输出信息如下:  
  76. smallFold.name=小羊圈  
  77. smallFold.number=10  
  78. smallFold.sheep=大羊  
  79. 大羊圈输出信息如下:  
  80. bigFold.name=大羊圈  
  81. bigFold.number=100  
  82. bigFold.sheep=大羊  
 
显然上面的这种复制是失败的,因为改动第二个对象中的名字后第一个对象的名字也发生了变化。要实现正确的复制,必须采用深度复制。其sheepfold类中clone方法的代码应改为如下:

 

Java代码    收藏代码
  1. 把上面的例子改成深度clone很简单,只需将Sheepfold的clone()方法改为如下即可:  
  2.     public Object clone() throws CloneNotSupportedException {  
  3.         Sheepfold fold = (Sheepfold)super.clone();  
  4.         sheep = (Sheep)fold.sheep.clone();  
  5.         return fold;  
  6.     }  
 另外,采用序列化也可以实现深度复制的效果。
代码如下:

 

Java代码    收藏代码
  1. /** 
  2.  *  
  3.  * @功能   羊对象类   
  4.  * @创建人   gao_jie 
  5.  * @创建日期 Jun 25, 2009 
  6.  * @版本     1.0 
  7.  *  
  8.  */  
  9. public class Sheep implements Serializable{  
  10.       
  11.     private String name;//名字  
  12.   
  13.     public String getName() {  
  14.         return name;  
  15.     }  
  16.   
  17.     public void setName(String name) {  
  18.         this.name = name;  
  19.     }  
  20. }  
  21.   
  22. public class Sheepfold implements Cloneable, Serializable {  
  23.     public Sheep sheep;// 羊对象  
  24.     public String name;// 羊圈名字  
  25.     public int number;// 数量  
  26.   
  27.     public Sheepfold() {  
  28.         this.sheep = new Sheep();  
  29.     }  
  30.   
  31.     /* 
  32.      * (non-Javadoc) 
  33.      *  
  34.      * @see java.lang.Object#clone() 
  35.      */  
  36.     public Object clone() throws CloneNotSupportedException {  
  37.         try {  
  38.             ByteArrayOutputStream bos = new ByteArrayOutputStream();  
  39.             ObjectOutputStream oos = new ObjectOutputStream(bos);  
  40.             oos.writeObject(this);  
  41.             // 将流序列化  
  42.             ByteArrayInputStream bis = new ByteArrayInputStream(bos  
  43.                     .toByteArray());  
  44.             ObjectInputStream ois = new ObjectInputStream(bis);  
  45.             return ois.readObject();  
  46.         } catch (IOException e) {  
  47.             e.printStackTrace();  
  48.         } catch (ClassNotFoundException e) {  
  49.             e.printStackTrace();  
  50.         }  
  51.         return null;  
  52.     }  
  53. }  
  54. 测试类  
  55. public class Test {  
  56.     public static void main(String[] args) {  
  57.         // 声明一个小羊圈对象  
  58.         Sheepfold smallFold = new Sheepfold();  
  59.         smallFold.name = "小羊圈";  
  60.         smallFold.number = 10;  
  61.         smallFold.sheep.setName("小羊");  
  62.         // 复制羊圈  
  63.         Sheepfold bigFold = null;  
  64.         try {  
  65.             bigFold = (Sheepfold) smallFold.clone();  
  66.         } catch (CloneNotSupportedException e) {  
  67.             // TODO Auto-generated catch block  
  68.             e.printStackTrace();  
  69.         }  
  70.         bigFold.name="大羊圈";  
  71.         bigFold.number=100;  
  72.         bigFold.sheep.setName("大羊");  
  73.           
  74.         System.out.println("小羊圈输出信息如下:");  
  75.         System.out.println("smallFold.name="+smallFold.name);  
  76.         System.out.println("smallFold.number="+smallFold.number);  
  77.         System.out.println("smallFold.sheep="+smallFold.sheep.getName());  
  78.         System.out.println("大羊圈输出信息如下:");  
  79.         System.out.println("bigFold.name="+bigFold.name);  
  80.         System.out.println("bigFold.number="+bigFold.number);  
  81.         System.out.println("bigFold.sheep="+bigFold.sheep.getName());  
  82.     }  
  83. }  
  84. 测试结果:  
  85. 小羊圈输出信息如下:  
  86. smallFold.name=小羊圈  
  87. smallFold.number=10  
  88. smallFold.sheep=小羊  
  89. 大羊圈输出信息如下:  
  90. bigFold.name=大羊圈  
  91. bigFold.number=100  
  92. bigFold.sheep=大羊  
 显然,序列化可以实现深度复制的效果,但每个非基本类型对象都必须是可序列化的。而设计模式中的原型啊模式也就是实现深度复制,因此,原型模式可以采用深度复制和序列化两种方式来实现。

    在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也就是说,AB是两个独立的对象,但B的初始值是由A对象确定的。在这种情况下常常使用clone。当然你完全可以new一个新的,让后再进行赋值。但应用clone会有如下的好处:

     1、实现clone方法比较简单、方便。

     2、Object类的clone()一个native方法,native方法的效率一般来说都是远高于java中的非native方法,因此clone方法是高效的。

    注意;通过序列化的方式也可以实现clone。如果一个对象包含复杂类型的变量时,可用序列化或深度clone来实现对象的clone。

 

浅度复制和深度复制

  
    在java中,对于基本类型的数据可采用浅度复制的方式进行对象的复制,其中做法就是直接继承Cloneable接口,调用Object类的clone()方法就可以了。而对于非基本类型的数据,复制方法只能采用深度复制或序列化的方式进行复制。
    典型的实例:
Java代码    收藏代码
  1. /** 
  2.  *  
  3.  * @功能   羊对象类   
  4.  * @创建人   gao_jie 
  5.  * @创建日期 Jun 25, 2009 
  6.  * @版本     1.0 
  7.  *  
  8.  */  
  9. public class Sheep implements Cloneable {  
  10.       
  11.     private String name;//名字  
  12.   
  13.     public String getName() {  
  14.         return name;  
  15.     }  
  16.   
  17.     public void setName(String name) {  
  18.         this.name = name;  
  19.     }  
  20.       
  21.     /* (non-Javadoc) 
  22.      * @see java.lang.Object#clone() 
  23.      */  
  24.     public Object clone() throws CloneNotSupportedException {  
  25.         return super.clone();  
  26.     }  
  27. }  
  28.   
  29. public class Sheepfold implements Cloneable {  
  30.      public Sheep sheep;//羊对象  
  31.      public String name;//羊圈名字  
  32.      public int number;//数量  
  33.   
  34.      public Sheepfold() {  
  35.          this.sheep = new Sheep();  
  36.      }  
  37.     /* (non-Javadoc) 
  38.      * @see java.lang.Object#clone() 
  39.      */  
  40.     public Object clone() throws CloneNotSupportedException {  
  41.         return super.clone();  
  42.     }  
  43. }  
  44.   
  45. public class Test {  
  46.     public static void main(String[] args) {  
  47.         // 声明一个小羊圈对象  
  48.         Sheepfold smallFold = new Sheepfold();  
  49.         smallFold.name = "小羊圈";  
  50.         smallFold.number = 10;  
  51.         smallFold.sheep.setName("小羊");  
  52.         // 复制羊圈  
  53.         Sheepfold bigFold = null;  
  54.         try {  
  55.             bigFold = (Sheepfold) smallFold.clone();  
  56.         } catch (CloneNotSupportedException e) {  
  57.             // TODO Auto-generated catch block  
  58.             e.printStackTrace();  
  59.         }  
  60.         bigFold.name="大羊圈";  
  61.         bigFold.number=100;  
  62.         bigFold.sheep.setName("大羊");  
  63.           
  64.         System.out.println("小羊圈输出信息如下:");  
  65.         System.out.println("smallFold.name="+smallFold.name);  
  66.         System.out.println("smallFold.number="+smallFold.number);  
  67.         System.out.println("smallFold.sheep="+smallFold.sheep.getName());  
  68.         System.out.println("大羊圈输出信息如下:");  
  69.         System.out.println("bigFold.name="+bigFold.name);  
  70.         System.out.println("bigFold.number="+bigFold.number);  
  71.         System.out.println("bigFold.sheep="+bigFold.sheep.getName());  
  72.     }  
  73. }  
  74. 测试结果:  
  75. 小羊圈输出信息如下:  
  76. smallFold.name=小羊圈  
  77. smallFold.number=10  
  78. smallFold.sheep=大羊  
  79. 大羊圈输出信息如下:  
  80. bigFold.name=大羊圈  
  81. bigFold.number=100  
  82. bigFold.sheep=大羊  
 
显然上面的这种复制是失败的,因为改动第二个对象中的名字后第一个对象的名字也发生了变化。要实现正确的复制,必须采用深度复制。其sheepfold类中clone方法的代码应改为如下:

 

Java代码    收藏代码
  1. 把上面的例子改成深度clone很简单,只需将Sheepfold的clone()方法改为如下即可:  
  2.     public Object clone() throws CloneNotSupportedException {  
  3.         Sheepfold fold = (Sheepfold)super.clone();  
  4.         sheep = (Sheep)fold.sheep.clone();  
  5.         return fold;  
  6.     }  
 另外,采用序列化也可以实现深度复制的效果。
代码如下:

 

Java代码    收藏代码
  1. /** 
  2.  *  
  3.  * @功能   羊对象类   
  4.  * @创建人   gao_jie 
  5.  * @创建日期 Jun 25, 2009 
  6.  * @版本     1.0 
  7.  *  
  8.  */  
  9. public class Sheep implements Serializable{  
  10.       
  11.     private String name;//名字  
  12.   
  13.     public String getName() {  
  14.         return name;  
  15.     }  
  16.   
  17.     public void setName(String name) {  
  18.         this.name = name;  
  19.     }  
  20. }  
  21.   
  22. public class Sheepfold implements Cloneable, Serializable {  
  23.     public Sheep sheep;// 羊对象  
  24.     public String name;// 羊圈名字  
  25.     public int number;// 数量  
  26.   
  27.     public Sheepfold() {  
  28.         this.sheep = new Sheep();  
  29.     }  
  30.   
  31.     /* 
  32.      * (non-Javadoc) 
  33.      *  
  34.      * @see java.lang.Object#clone() 
  35.      */  
  36.     public Object clone() throws CloneNotSupportedException {  
  37.         try {  
  38.             ByteArrayOutputStream bos = new ByteArrayOutputStream();  
  39.             ObjectOutputStream oos = new ObjectOutputStream(bos);  
  40.             oos.writeObject(this);  
  41.             // 将流序列化  
  42.             ByteArrayInputStream bis = new ByteArrayInputStream(bos  
  43.                     .toByteArray());  
  44.             ObjectInputStream ois = new ObjectInputStream(bis);  
  45.             return ois.readObject();  
  46.         } catch (IOException e) {  
  47.             e.printStackTrace();  
  48.         } catch (ClassNotFoundException e) {  
  49.             e.printStackTrace();  
  50.         }  
  51.         return null;  
  52.     }  
  53. }  
  54. 测试类  
  55. public class Test {  
  56.     public static void main(String[] args) {  
  57.         // 声明一个小羊圈对象  
  58.         Sheepfold smallFold = new Sheepfold();  
  59.         smallFold.name = "小羊圈";  
  60.         smallFold.number = 10;  
  61.         smallFold.sheep.setName("小羊");  
  62.         // 复制羊圈  
  63.         Sheepfold bigFold = null;  
  64.         try {  
  65.             bigFold = (Sheepfold) smallFold.clone();  
  66.         } catch (CloneNotSupportedException e) {  
  67.             // TODO Auto-generated catch block  
  68.             e.printStackTrace();  
  69.         }  
  70.         bigFold.name="大羊圈";  
  71.         bigFold.number=100;  
  72.         bigFold.sheep.setName("大羊");  
  73.           
  74.         System.out.println("小羊圈输出信息如下:");  
  75.         System.out.println("smallFold.name="+smallFold.name);  
  76.         System.out.println("smallFold.number="+smallFold.number);  
  77.         System.out.println("smallFold.sheep="+smallFold.sheep.getName());  
  78.         System.out.println("大羊圈输出信息如下:");  
  79.         System.out.println("bigFold.name="+bigFold.name);  
  80.         System.out.println("bigFold.number="+bigFold.number);  
  81.         System.out.println("bigFold.sheep="+bigFold.sheep.getName());  
  82.     }  
  83. }  
  84. 测试结果:  
  85. 小羊圈输出信息如下:  
  86. smallFold.name=小羊圈  
  87. smallFold.number=10  
  88. smallFold.sheep=小羊  
  89. 大羊圈输出信息如下:  
  90. bigFold.name=大羊圈  
  91. bigFold.number=100  
  92. bigFold.sheep=大羊  
 显然,序列化可以实现深度复制的效果,但每个非基本类型对象都必须是可序列化的。而设计模式中的原型啊模式也就是实现深度复制,因此,原型模式可以采用深度复制和序列化两种方式来实现。

猜你喜欢

转载自rongdmmap-126-com.iteye.com/blog/1434346