Java clone方法浅析

来源:互联网 发布:手机怎么找到淘宝客服 编辑:程序博客网 时间:2024/06/14 09:34

Java clone方法浅析

什么是clone()?

Java的所有类都默认继承java.lang.Object类,在java.lang.Object类中有一个方法clone()。JDK API的说明文档解释这个方法将返回Object对象的一个拷贝。要说明的有两点:

  1. 拷贝对象返回的是一个新对象,而不是一个引用。
  2. 拷贝对象与用 new操作符返回的新对象的区别就是这个拷贝已经包含了一些原来对象的信息,而不是对象的初始信息。

clone()的实现

class CloneClass implements Cloneable{  public int aInt;  public Object clone(){   CloneClass o = null;   try{    o = (CloneClass)super.clone();   }catch(CloneNotSupportedException e){    e.printStackTrace();   }   return o;  } }

实现Cloneable接口,Cloneable接口是不包含任何方法的!其实这个接口仅仅是一个标志,而且这个标志也仅仅是针对 Object类中clone()方法的,如果clone类没有实现Cloneable接口,并调用了Object的clone()方法(也就是调用了 super.Clone()方法),那么Object的clone()方法就会抛出CloneNotSupportedException异常。

clone()new的区别

在java语言中,有2种方式可以创建对象:

  1. 使用new操作符创建一个对象
  2. 使用clone方法复制一个对象

那么这两种方式有什么相同和不同呢?

  1. new操作符的本意是分配内存。程序执行到new操作符时, 首先去看new操作符后面的类型,因为知道了类型,才能知道要分配多大的内存空间。分配完内存之后,再调用构造函数,填充对象的各个域,这一步叫做对象的初始化,构造方法返回后,一个对象创建完毕,可以把他的引用(地址)发布到外部,在外部就可以使用这个引用操纵这个对象。
  2. 而clone在第一步是和new相似的, 都是分配内存,调用clone方法时,分配的内存和源对象(即调用clone方法的对象)相同,然后再使用原对象中对应的各个域,填充新对象的域, 填充完成之后,clone方法返回,一个新的相同的对象被创建,同样可以把这个新对象的引用发布到外部。

上例子

  • new
Person p = new Person(23, "zhang");  Person p1 = p;  System.out.println(p);  System.out.println(p1); /* output *---------------------- * Person@2f9ee1ac * Person@2f9ee1ac */
  • clone()
Person p = new Person(23, "zhang");  Person p1 = (Person) p.clone();  System.out.println(p);  System.out.println(p1); /* output *---------------------- * Person@2f9ee1ac * Person@67f1fba0 */ 

显然,new 操作只是把句柄的引用地址传递出去了,所以句柄指向同一个地址。而clone()创建了一个新的对象。

影子clone和深度clone

public class Person implements Cloneable{      private int age ;      private String name;      public Person(int age, String name) {          this.age = age;          this.name = name;      }      public Person() {}      public int getAge() {          return age;      }      public String getName() {          return name;      }      @Override      protected Object clone() throws CloneNotSupportedException {          return (Person)super.clone();      }  }

Person中有两个成员变量,分别是name和age, name是String类型, age是int类型。

name是String类型的,它只是一个引用,指向一个真正的String对象,那么对它的拷贝有两种方式:直接将源对象中的name的引用值拷贝给新对象的name字段,或者是根据原Person对象中的name指向的字符串对象创建一个新的相同的字符串对象,将这个新字符串对象的引用赋给新拷贝的Person对象的name字段。这两种拷贝方式分别叫做影子克隆和深度克隆。默认的克隆方式是影子克隆,实现深度克隆可以通过重写clone方法,除了调用父类中的clone方法得到新的对象,还要将该类中的引用变量也clone出来。

原创粉丝点击