克隆的理解

一、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对象不同


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值