为什么要用clone?
在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中
已经包含了一些有效值,此时可能会需要一个和A完全相同的新对象B,并且以
后对B任何改动都不会影响A中的值,也就是说A与B是两个独立的对象,但B的
初始值由A对象确定的. 在Java语言中用简单的赋值语句是不能满足这种需求的.
要满足这种需求虽然有很多途径,但实现clone()方法是其中最简单的也是最高效的手段.
new一个对象的过程和clone一个对象的过程区别
new操作符的本意是分配内存.程序执行到new操作符时,首先去看new操作符后面的类型,
因为知道了类型才能知道要分配多大的内存空间. 分配完内存以后,再调用构造函数,
填充对象的各个域. 这一步叫做初始化.构造方法返回后,一个对象创建完毕,
可以把它的引用(地址)发布到外部, 在外部就可以使用这个引用操作这个对象.
clone在第一步和new相似, 都是分配内存,调用clone方法时, 分配的内存
和原对象(调用clone方法的对象)相同, 然后再使用原对象中对应的各个域填充
新对象的域, 填充完成之后, clone方法返回一个新的相同的对象,同样可以把这
个新对象的引用发布到外部,就可以使用这个引用操作这个新对象.
浅克隆和深克隆(深拷贝和浅拷贝)
定义一个Person对象类实现Cloneable接口重写clone()方法如下:
package com.ganbo;
/**
* Created by gan on 2018/3/13 17:18.
*/
public class Person implements Cloneable {
private String name;
private Integer age;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return super.toString();
}
}
编写测试代码:
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person("Bruce", 23);
Person p2 = (Person) p1.clone(); //克隆对象
System.out.println(p1 == p2);
System.out.println(p1.getName() == p2.getName());
}
运行结果为:
false证明调用clone方法是克隆了一个新对象.
true表示p1和p2对象name属性其实还是同一个字符串对象. 这种调用克隆方法后属性并没有创建新对象叫
浅克隆.所以克隆方法执行调用的是浅拷贝,在编写程序的时候就要注意这个细节.
如何进行深拷贝 ?
如果要想深拷贝一个对象,这个对象必须实现Cloneable接口,实现clone方法, 并且在clone方法内部要把
该对象的其他对象也要clone一份, 这就要求这个这个被引用的对象也必须要实现Cloneable接口并实现clone
方法. 那么如下代码所示:
package com.ganbo;
/**
* Created by gan on 2018/3/13 17:18.
*/
public class Person implements Cloneable {
private Integer age;
private Book book;
public Person(Integer age, Book book) {
this.age = age;
this.book = book;
}
public void setAge(Integer age) {
this.age = age;
}
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
public Integer getAge() {
return age;
}
/**
* 实现clone方法,并且在方法中把依赖的对象也clone一份
*
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
Person newPerson = (Person) super.clone();
newPerson.book = (Book) book.clone();
return newPerson;
}
}
class Book implements Cloneable {
private Long id;
public Book(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
编写测试代码:
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person(23,new Book(12L));
Person p2 = (Person) p1.clone(); //克隆对象
System.out.println(p1.book == p2.book);
}
打印结果为:
完成深克隆.