克隆的理解

一、Cloneable 的用途 
Cloneable和Serializable一样都是标记型接口,它们内部都没有方法和属性,implements Cloneable表示该对象能被克隆,能使用Object.clone()方法。如果没有implements Cloneable的类调用Object.clone()方法就会抛出CloneNotSupportedException。

二、克隆的分类
1、浅克隆(shallow clone
     拷贝对象的时候仅仅拷贝对象本身和对象中的基本变量,而不拷贝对象中包含的引用所指向的对象。
2、深克隆(deep clone
     拷贝对象的时候不仅仅拷贝对象本身,同时拷贝对象所包含的的引用所指向的对象。
举例说明:
对象A1中包含对B1的引用,B1中包含对C1的引用。
浅拷贝A1得到A2,A2中依然包含对B1的引用,B1中依然包含对C1的引用。深拷贝则是对浅拷贝的递归,深拷贝A1得到A2,A2中包含对B2(B1的copy)的引用,B2中包含对C2(C1的copy)的引用。 

三、克隆的举例
要让一个对象进行克隆,其实就是两个步骤: 
      1、让类实现java.lang.Cloneable接口
      2、重写(override) Object类的clone()方法
代码实现:
package com.tyxh.create;

public class Wife implements Cloneable {
     private int id;
     private String name;

     public int getId() {
           return id;
     }

     public void setId( int id) {
           this. id = id;
     }

     public String getName() {
           return name;
     }

     public void setName(String name) {
           this. name = name;
     }

     public Wife( int id,String name) {
           this. id = id;
           this. name = name;
     }

     @Override
     public int hashCode() {
           final int prime = 31;
           int result = 1;
          result = prime * result + id;
          result = prime * result + (( name == null) ? 0 : name.hashCode());
           return result;
     }
     
     @Override
     public boolean equals (Object obj) {
           if ( this == obj)
               return true;
           if (obj == null)
               return false;
           if (getClass() != obj.getClass())
               return false;
          Wife other = (Wife) obj;
           if ( id != other. id)
               return false;
           if ( name == null) {
               if (other. name != null)
                    return false;
          } else if (! name.equals(other. name))
               return false;
           return true;
     }

     @Override
     public Object clone() throws CloneNotSupportedException {
           return super.clone();
     }

     public static void main(String[] args) throws CloneNotSupportedException {
          Wife wife = new Wife(1, "wang");
          Wife wife2 = null;
          wife2 = (Wife) wife.clone();
          System. out.println( "wife  : " + wife);
          System. out.println( "wife2 : " + wife2);
          wife.setName( "tyxh");
          System. out.println( "wife  : " + wife);
          System. out.println( "wife2 : " + wife2);
          wife2.setName( "sotaof");
          System. out.println( "wife  : " + wife);
          System. out.println( "wife2 : " + wife2);
           //上面两个输出的地址相同,克隆的只是引用
          System. out.println( "class same="+(wife.getClass()==wife2.getClass())); //true
          System. out.println( "object same="+(wife==wife2));//false 说明两个对象的地址不同
          System. out.println( "object equals="+(wife.equals (wife2)));//false
     }
}

输入结果:
wife  : com.tyxh.create.Wife@3795e3
wife2 : com.tyxh.create.Wife@3795e3
wife  : com.tyxh.create.Wife@369415
wife2 : com.tyxh.create.Wife@3795e3
wife  : com.tyxh.create.Wife@369415
wife2 : com.tyxh.create.Wife@ca8fb940
class same=true
object same=false
object equals=false

第一行和第二行相同的原因不是因为克隆后的wife和wife2地址相同,而是因为hashcode的缘故,我们注意hashcode的返回值result = prime * result + (( name == null) ? 0 : name.hashCode());name变化的话,返回值就会发生改变。如果你在hashcode方法中返回1,那么结果就会是@1;

当对wife的name值进行修改之后,wife的值变化了,而wife2的值没有变化;

当对wife2的name值进行修改之后,wife2的值变化了,而wife的值没有变化

但是这并不代表wife和wife2的地址发生了改变,这仅仅能说明wife和wife2的值发生了改变。当我们注释掉hashCode()和equals()方法之后,再看一下输出结果:

wife  : com.tyxh.create.Wife@3771ed5e
wife2 : com.tyxh.create.Wife@1896d2c2
wife  : com.tyxh.create.Wife@3771ed5e
wife2 : com.tyxh.create.Wife@1896d2c2
wife  : com.tyxh.create.Wife@3771ed5e
wife2 : com.tyxh.create.Wife@1896d2c2
class same=true
object same=false
object equals=false

通过结果可以看出,不管是对wife还是对wife2进行值的修改,它们的地址都没有改变。

四.浅克隆的举例 
package com.tyxh.create;

public class Husband implements Cloneable {
     private int id;
     private Wife wife;
     
     public Wife getWife() {
           return wife;
     }

     public void setWife(Wife wife) {
           this. wife = wife;
     }

     public int getId() {
           return id;
     }

     public void setId( int id) {
           this. id = id;
     }

     public Husband( int id) {
           this. id = id;
     }

     @Override
     public int hashCode() { 
           final int prime = 31;
           int result = 1;
          result = prime * result + id;
           return result;
     }

     @Override
     protected Object clone() throws CloneNotSupportedException {
           return super.clone();
     }

     @Override
     public boolean equals(Object obj) {
           if ( this == obj)
               return true;
           if (obj == null)
               return false;
           if (getClass() != obj.getClass())
               return false;
          Husband other = (Husband) obj;
           if ( id != other. id)
               return false;
           return true;
     }

     /**
      * @param args
      * @throws CloneNotSupportedException
      */
     public static void main(String[] args) throws CloneNotSupportedException {
          Wife wife = new Wife(1, "jin");
          Husband husband = new Husband(1);
          Husband husband2 = null;
          husband.setWife(wife);
          husband2 = (Husband) husband.clone();
          System. out.println( "husband  : " + husband);
          System. out.println( "husband2 : " + husband2);
          System. out.println( "husband class same="+(husband.getClass()==husband2.getClass())); //true
          System. out.println( "husband object same="+(husband==husband2));//false
          System. out.println( "husband object equals="+(husband.equals(husband)));//true
          System. out.println( "wife class same="+(husband.getWife().getClass()==husband2.getWife().getClass())); //true
          System. out.println( "wife object same="+(husband.getWife()==husband2.getWife())); //true 说明引用是同一个引用
          System. out.println( "wife object equals="+(husband.getWife().equals(husband.getWife()))); //true
     }
}

输入结果如下:
husband  : com.tyxh.create.Husband@20
husband2 : com.tyxh.create.Husband@20
husband class same=true
husband object same=false
husband object equals=true
wife class same=true
wife object same=true
wife object equals=true

四.深克隆的举例 
package com.tyxh.create;

public class Husband implements Cloneable {
     private int id;
     private Wife wife;
     
     public Wife getWife() {
           return wife;
     }

     public void setWife(Wife wife) {
           this. wife = wife;
     }

     public int getId() {
           return id;
     }

     public void setId( int id) {
           this. id = id;
     }

     public Husband( int id) {
           this. id = id;
     }

     @Override
     public int hashCode() { //myeclipse 自动生成的
           final int prime = 31;
           int result = 1;
          result = prime * result + id;
           return result;
     }

     @Override
     protected Object clone() throws CloneNotSupportedException {
          Husband husband = (Husband) super.clone();
          husband. wife = (Wife) husband.getWife().clone();
           return husband;
     }

     @Override
     public boolean equals(Object obj) { //myeclipse 自动生成的
           if ( this == obj)
               return true;
           if (obj == null)
               return false;
           if (getClass() != obj.getClass())
               return false;
          Husband other = (Husband) obj;
           if ( id != other. id)
               return false;
           return true;
     }

     /**
      * @param args
      * @throws CloneNotSupportedException
      */
     public static void main(String[] args) throws CloneNotSupportedException {
          Wife wife = new Wife(1, "jin");
          Husband husband = new Husband(1);
          Husband husband2 = null;
          husband.setWife(wife);
          husband2 = (Husband) husband.clone();
          System. out.println( "husband  : " + husband);
          System. out.println( "husband2 : " + husband2);
          System. out.println( "husband class same="+(husband.getClass()==husband2.getClass())); //true
          System. out.println( "husband object same="+(husband==husband2));//false
          System. out.println( "husband object equals="+(husband.equals(husband)));//true
          System. out.println( "wife class same="+(husband.getWife().getClass()==husband2.getWife().getClass())); //true
          System. out.println( "wife object same="+(husband.getWife()==husband2.getWife())); //false 说明引用不是同一个引用
          System. out.println( "wife object equals="+(husband.getWife().equals(husband.getWife()))); //true
     }
}

输出结果如下:
husband  : com.tyxh.create.Husband@20
husband2 : com.tyxh.create.Husband@20
husband class same=true
husband object same=false
husband object equals=true
wife class same=true
wife object same=false
wife object equals=true

五、通过反序列化克隆 (也是深克隆)
package com.tyxh.create;

import java.io.*;

public class BeanUtil {
     @SuppressWarnings( "unchecked")
     public static <T> T cloneTo(T src) {
          ByteArrayOutputStream memoryBuffer = new ByteArrayOutputStream();
          ObjectOutputStream out = null;
          ObjectInputStream in = null;
          T dist = null;
          
           try {
              out = new ObjectOutputStream(memoryBuffer);
              out.writeObject(src);
              out.flush();
              
              in = new ObjectInputStream( new ByteArrayInputStream(memoryBuffer.toByteArray()));
              dist = (T) in.readObject();
              
          } catch (Exception e) {
              e.printStackTrace();
          } finally {
               if(out != null) {
                    try {
                        out.close();
                   } catch (IOException e) {
                        e.printStackTrace();
                   }
              }
               if(in != null) {
                    try {
                        in.close();
                   } catch (IOException e) {
                        e.printStackTrace();
                   }
              }
          }
                   
           return dist;
     }
     
     public static void main(String[] args) {
          Husband husband = new Husband(1);
          Wife wife = new Wife(1, "jin");
          husband.setWife(wife);
          Husband husband2 = cloneTo(husband);
          System. out.println("husband class same="+(husband.getClass()==husband2.getClass())); //true
          System. out.println( "husband object same="+(husband==husband2));//false
          System. out.println("husband object equals="+(husband.equals(husband)));//true
          System. out.println("wife class same="+(husband.getWife().getClass()==husband2.getWife().getClass())); //true
          System. out.println("wife object same="+(husband.getWife()==husband2.getWife())); //false 说明引用不是同一个引用
          System. out.println("wife object equals="+(husband.getWife().equals(husband.getWife()))); //true
     }
}

输出结果如下:
husband class same=true
husband object same=false
husband object equals=true
wife class same=true
wife object same=false
wife object equals=true

通过第二行可以看出,反序列化之后的husband2与husband不是同一个对象
通过第五行可以看出,反序列化属于一种深克隆,因为husband和husband2的wife对象不同


发布了146 篇原创文章 · 获赞 37 · 访问量 93万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章