zoukankan      html  css  js  c++  java
  • 分析java中clone()方法 (转载+修改)

      Java中的clone() 方法
    

    java所有的类都是从java.lang.Object类继承而来的,而Object类提供下面的方法对对象进行复制。

     protected native Object clone() throws CloneNotSupportedException;

    这个javabean必须实现一个标识接口,Cloneable,表明这个javabean支持复制,如果没有实现这个接口,而调用clone()方法,编译器就会抛出CloneNotSupportedException异常。java语言提供的Cloneable接口只起一个作用,就是在运行时通知虚拟机可以安全的在这个类上使用clone方法,通过调用这个clone()方法可以得到一个对象的复制(Object 类本身不实现Cloneable接口);

    克隆满足的条件:

    clone()方法将对象复制了一份并返还给调用者。所谓“复制”的含义与clone()方法是怎么实现的有关。一般而言,clone方法满足以下条件:

    1).对任何的对象x,都有:x.clone()!=x.即克隆对象与原对象不是同一个对象。

    2).对任何的对象x,都有:x.clone().getClass==x.getClass(),即克隆对象与原对象的类型一样。

    3).如果对象x的equals()方法定义恰当的话,x.clone().equals(x)应当是成立的。

    克隆分为两种方式:深克隆和浅克隆

    浅克隆(浅复制):被复制对象的所有变量都含有与原来对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。

    深克隆(深复制):被复制对象的所有变量(非引用其他对象的变量)都含有与原来的对象相同的值,那些引用其他的对象的变量将指向被复制过的新对象,而不是原有的那些被引用的对象。即:深复制把要复制的对象所引用的对象都复制了一遍,而这种堆被引用的对象的复制叫做间接复制。

    以下是浅复制的例子:

    ====================================================================================

    客户端:
    
    public class TheGreatestSage
     {
      
      private Monkey monkey=new Monkey();
      public void change()
       {
       	  Monkey copy;
       	  copy=(Monkey)monkey.clone();
      	  System.out.println("原来生日:"+monkey.getBirthday());
      	  System.out.println("复制的生日:"+copy.getBirthday());
       	  System.out.println("猴子是不是一个对象"+(monkey==copy));
        	  System.out.println("金箍棒是否是一个"+(monkey.getStaff()==copy.getStaff()));
       }
      public static void main(String args[])
       {
        	 new TheGreatestSage().change();
       }
     }
    
    猴子类(可以复制的类)
    
    import java.util.Date;
    
    public class Monkey implements Cloneable
     {
      private int height;
      private int weight;
      private GoldRingedStaff staff;
      private Date birthday;
      public Monkey()
       {
        	this.birthday=new Date();
       }
      public Date getBirthday()
       {
        	return birthday;
       }
      public void setBirthday(Date birthday)
       {
       	 this.birthday = birthday;
       }
      public int getHeight()
       {
       	 return height;
       }
      public void setHeight(int height)
       {
        	this.height = height;
       }
      public GoldRingedStaff getStaff()
       {
       	 return staff;
       }
      public void setStaff(GoldRingedStaff staff)
       {
        	this.staff = staff;
       }
      public int getWeight()
       {
       	 return weight;
       }
      public void setWeight(int weight)
       {
        	this.weight = weight;
       }
      public Object clone()
       {
       	 Monkey temp=null;
       	 try
         {
         	 temp=(Monkey)super.clone();
          }
        catch (CloneNotSupportedException e)
         {
        	  // TODO 自动生成 catch 块
         	 e.printStackTrace();
         }
        finally
        {
        	 return temp;
        }
       }
     }
    
    金箍棒(复制类引用的类)
    
    public class GoldRingedStaff
     {
      private  float height=100.0f;
      private float diameter=10.0f;
      public void grow()
       {
        	this.height*=2.0;
        	this.diameter*=2;
       }
      public void shrink()
       {
        	this.height/=2;
       	 this.diameter/=2;
       }
      public float getDiameter()
       {
       	 return diameter;
       }
      public void setDiameter(float diameter)
       {
       	 this.diameter = diameter;
       }
      public float getHeight()
       {
       	 return height;
       }
      public void setHeight(float height)
       {
       	 this.height = height;
       }
      
     }


    ====================================================================================

    运行结果:

    原来生日:Mon May 07 09:27:12 CST 2007
    复制的生日:Mon May 07 09:27:12 CST 2007
    猴子是不是一个对象false
    金箍棒是否是一个true

    由结果可以看出:

    复制的对象和原来的对象有相同的生日,而对象本身不相等。说明他们是克隆关系。 但复制的对象和原对象的金箍棒是一样的,说明二者持有的是同一个对象。

    ####################################################################################

    深克隆例子:

    为了做到深复制,所有需要复制的对象都要实现java.io.Serializable接口。

    =========================================================================================

    客户端
    
    import java.io.IOException;
    
    public class TheGreatestSage
     {
      private Monkey monkey=new Monkey();
      public void change() throws IOException, ClassNotFoundException
       {
       	 Monkey copy;
        	copy=(Monkey)monkey.deepClone();
        	System.out.println("原来生日:"+monkey.getBir());
        	System.out.println("复制的生日:"+copy.getBir());
        	System.out.println("猴子是不是一个对象"+(monkey==copy));
       	 System.out.println("金箍棒是否是一个"+(monkey.getStaff()==copy.getStaff()));
       }
      public static void main(String args[]) throws IOException, ClassNotFoundException
       {
      	  new TheGreatestSage().change();
       }
     }
    
    猴子类(可以复制的类)
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    import java.util.Date;
    
    public class Monkey implements Cloneable,Serializable
     {
      private int height;
      private int weight;
      private GoldRingedStaff staff;
      private Date bir;
      public Monkey()
       {
        	this.bir=new Date();
        	this.staff=new GoldRingedStaff();
       }
      public Date getBir()
       {
       	 return bir;
       }
      public void setBir(Date bir)
       {
     	  this.bir = bir;
       }
      public int getHeight()
       {
      	  return height;
       }
      public void setHeight(int height)
       {
       	 this.height = height;
       }
      public GoldRingedStaff getStaff()
       {
       	 return staff;
       }
      public void setStaff(GoldRingedStaff staff)
       {
        	this.staff = staff;
       }
      public int getWeight()
       {
       	 return weight;
       }
      public void setWeight(int weight)
       {
       	 this.weight = weight;
       }
      /*
       * 深克隆方法
       */
      public Object deepClone() throws IOException, ClassNotFoundException 
       {
        //首先将对象写到流里
       	 ByteArrayOutputStream bo=new ByteArrayOutputStream();
       	 ObjectOutputStream oo=new  ObjectOutputStream(bo);
        	oo.writeObject(this);
        //然后将对象从流里读出来
       	 ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
       	 ObjectInputStream oi=new ObjectInputStream(bi);
       	 return (oi.readObject());
       }
      /*
       * 浅克隆方法
       */
      public Object clone()
       {
       	 Monkey temp=null;
        try
         {
         	 temp=(Monkey)(super.clone());
         }
        catch (CloneNotSupportedException e)
         {
         	 // TODO 自动生成 catch 块
        	  e.printStackTrace();
         }
       	 return temp;
       }
     }
    
    金箍棒(复制类引用的类)
    
    import java.io.Serializable;
    
    public class GoldRingedStaff implements Cloneable,Serializable
     {
      private float height=100f;
      private float diameter=10.0f;
      public void grow()
       {
        	this.height*=2;
       	this.diameter*=2;
       }
      public void shrink()
       {
       	 this.height/=2;
      	  this.diameter/=2;
       }
      public float getDiameter()
       {
       	 return diameter;
       }
      public void setDiameter(float diameter)
       {
        	this.diameter = diameter;
       }
      public float getHeight()
       {
        	return height;
       }
      public void setHeight(float height)
       {
       	 this.height = height;
       }
     }


    =========================================================================================

    运行结果

    原来生日:Mon May 07 10:38:21 CST 2007
    复制的生日:Mon May 07 10:38:21 CST 2007
    猴子是不是一个对象false
    金箍棒是否是一个false

    由结果可以看出:使用了深复制,除了将目标类复制,也把所有引用的的对象都复制了一遍。


    ===================================

    ===================================

    ===================================

    ===================================

    浅析java中clone()方法 

            java中我们可能都遇到过这样的情况,在我们将一个对象做为参数传给一个函数的时候,我们希望在这个函数中所做的操做,并不会影响到这个对象本身。但是在java传递都是引用,所以往往我们在函数内部改变了对象的某一个值,在函数外面调用该对象的时候,相应的值也同样被改变了,例如下面的程序:

    class Test

    {

    static void myMethod(Point pt1)

    {

    pt1.x = 23;

    System.out.println("x="+pt1.x);

    }


       public static void main(String[] args)

    {

    Point pt = new Point(2,4);

    System.out.println("x="+pt.x);

    myMethod(pt);

    System.out.println("x="+pt.x);

    }

    }

    class Point{

       int x,y;   

       Point (int x,int y)

       {

           this.x = x;

          this.y = y;

       }

    }

    输出的结果是

    x=2

    x=23

    x=23

    但是我们想要的结果是在我们调用了函数myMethod()方法后x的值不会改变,仍然是2。由于java中的传参是引用类型,所以会出现这样的结果,我们希望传递的是对象的一份拷贝,所以这里就用到了Object的clone()方法。

           克隆的实现需要一下几步:

    在派生类中覆盖基类的clone()方法,并声明为public。

    在派生类的clone()方法中,调用super.clone()。

    在派生类中实现Cloneable接口。Cloneable接口没有任何抽象的方法,这样的成为标识接口。实现这个接口,只是为了告诉编译器这个对象可以被克隆了。我们按照上面的步骤将上面的代码修改如下:

    class Test
    {
    static void   myMethod(Point pt1)
    {
    pt1.x = 23;
    System.out.println("x="+pt1.x);
    }
       public static void main(String[] args)
       {
      Point pt = new Point(2,4);
      System.out.println("x="+pt.x);
      Point pt2 = (Point)pt.clone();
      myMethod(pt2);
      System.out.println("x="+pt.x);
       }
    }
    class Point implements Cloneable{
       int x,y;   
       Point (int x,int y)
       {
           this.x = x;
          this.y = y;
       }
       public Object clone()
       {
      Point p = null;
      try
      {
      p = (Point)super.clone();
      }
      catch (Exception e)
      {
      e.printStackTrace();
      }
      return p;
       }
    }

    输出的结果是:

    x=2
    x=23
    x=2

    首先我们在派生类中覆盖了Object类的Clone()方法,并声明为public的。然后我们调用了super.clone()方法,这里会抛出一个异常(对于这个异常大家可以自己查看java的帮助文档),所以必须用try……catch……语句捕获,然后返回此对象。这里需要说明一下,Clone()方法返回的是Object类型的,所以需要强制类型转换

           对于javaclone()方法的浅析希望能给您带来帮助。



    ==

  • 相关阅读:
    虚拟机的Linux 安装 若干问题(一)
    理解JavaScript的闭包
    javascript里面的引用类型和值类型
    javascript导入自定义模块
    简单了解下CAP定理与BASE定理
    背包问题之完全背包
    背包问题之多重背包
    背包问题之0-1背包
    搜索算法初步总结
    谈一谈“回溯法“
  • 原文地址:https://www.cnblogs.com/new0801/p/6175854.html
Copyright © 2011-2022 走看看