Java Clone 学习
原文地址:详解Java中的clone方法
通常在Java中我们通过new关键字创建对象,代码如下:
Human human = new Human();
Human human2 = human;
System.out.println("human is :" + human);
System.out.println("human2 is :" + human2);
打印如下:
human is :TestClone$Human@6d06d69c
human2 is :TestClone$Human@6d06d69c
从结果看出human2和human指向了同一对象,从这行代码页印证了引用即是Java种的指针这一说法。
Java中创建对象的方法有很多,常见的有:
- new 使用new关键字首先为新对象创建内存,然后使用构造函数为新对象的各个Field初始化
- clone 首先为新对象创建内存,然后使用旧的对象的值填充新的对象的各个Field
- readobject 首先为新对象创建内存,从流中读取数据,并填充新对象的各个Field
Clone 方法
Clone 定义在Object类中的保护方法,一个类如果要支持Clone,需要按照下面的两个步骤编写代码。
- 重写Clone方法
- 实现Cloneable接口 - Cloneable是一个标记接口,实现这个接口只需要在顶一类是声明即可,如果类未实现Cloneable接口,调用其Clone方法会抛出CloneNotSupportedException
一个例子:
static class Human implements Cloneable {
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public static void main(String[] args) {
Human human1 = new Human();
System.out.println("human is :" + human1);
try {
Human human2 = (Human) human1.clone();
System.out.println("human2 is :" + human2);
} catch (CloneNotSupportedException e) {
System.out.println("human CloneNotSupportedException");
}
}
运行结果为:
human is :TestClone$Human@6d06d69c
human2 is :TestClone$Human@7852e922
从运行结果看,Clone方法创建了新的对象。
深复制和浅复制
浅复制
浅复制是指为新的对象创建内存,并使用旧的对象的中的引用的值填充新的对象中引用的值,观察如下代码:
static class Human implements Cloneable {
public Head mHead;
public Human(Head head) {
mHead = head;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public static void main(String[] args) {
Human human1 = new Human(new Head());
try {
Human human2 = (Human) human1.clone();
System.out.println("human1 is :" + human1);
System.out.println("human2 is :" + human2);
System.out.println("human1 head is :" + human1.mHead);
System.out.println("human2 head is :" + human2.mHead);
} catch (CloneNotSupportedException e) {
System.out.println("human CloneNotSupportedException");
}
}
运行结果:
human1 is :TestClone$Human@6d06d69c
human2 is :TestClone$Human@7852e922
human1 head is :TestClone$Head@4e25154f
human2 head is :TestClone$Head@4e25154f
从运行结果看,Object类中Clone方法的实现为浅复制
深复制
深复制是指,为新的对象申请内存,并未其中的每个引用申请内存。将上述的代码改造如下:
static class Head implements Cloneable {
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
static class Human implements Cloneable {
public Head mHead;
public Human(Head head) {
mHead = head;
}
public Object clone() throws CloneNotSupportedException {
Human human = (Human) super.clone();
human.mHead = (Head) mHead.clone();
return human;
}
}
public static void main(String[] args) {
Human human1 = new Human(new Head());
try {
Human human2 = (Human) human1.clone();
System.out.println("human1 is :" + human1);
System.out.println("human2 is :" + human2);
System.out.println("human1 head is :" + human1.mHead);
System.out.println("human2 head is :" + human2.mHead);
} catch (CloneNotSupportedException e) {
System.out.println("human CloneNotSupportedException");
}
}
结果如下:
human1 is :TestClone$Human@6d06d69c
human2 is :TestClone$Human@7852e922
human1 head is :TestClone$Head@4e25154f
human2 head is :TestClone$Head@70dea4e
从结果看human和head都指向了新的对象(内存)。
继续改造上述代码:
static class Face {
}
static class Head implements Cloneable {
Face mFace;
public Head() {
mFace = new Face();
}
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
static class Human implements Cloneable {
public Head mHead;
public Human(Head head) {
mHead = head;
}
public Object clone() throws CloneNotSupportedException {
Human human = (Human) super.clone();
human.mHead = (Head) mHead.clone();
return human;
}
}
public static void main(String[] args) {
Human human1 = new Human(new Head());
try {
Human human2 = (Human) human1.clone();
System.out.println("human1 is :" + human1);
System.out.println("human2 is :" + human2);
System.out.println("human1 head is :" + human1.mHead);
System.out.println("human2 head is :" + human2.mHead);
System.out.println("human1 face is :" + human1.mHead.mFace);
System.out.println("human2 face is :" + human2.mHead.mFace);
} catch (CloneNotSupportedException e) {
System.out.println("human CloneNotSupportedException");
}
}
运行结果如下:
human1 is :TestClone$Human@6d06d69c
human2 is :TestClone$Human@7852e922
human1 head is :TestClone$Head@4e25154f
human2 head is :TestClone$Head@70dea4e
human1 face is :TestClone$Face@5c647e05
human2 face is :TestClone$Face@5c647e05
从结果看face又指向了相同对象(引用),为了完成彻底的深复制,需要对Face类和Head类做如下改造:
static class Face implements Cloneable {
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
static class Head implements Cloneable {
Face mFace;
public Head() {
mFace = new Face();
}
protected Object clone() throws CloneNotSupportedException {
Head head = (Head) super.clone();
head.mFace = (Face) mFace.clone();
return head;
}
}
结果如下:
human1 is :TestClone$Human@6d06d69c
human2 is :TestClone$Human@7852e922
human1 head is :TestClone$Head@4e25154f
human2 head is :TestClone$Head@70dea4e
human1 face is :TestClone$Face@5c647e05
human2 face is :TestClone$Face@33909752
结论
- Object类提供了Clone方法用于复制对象,
- 一个类如果要支持Clone,需要重写Clone方法,并实现Cloneable接口
- Object类的Clone实现为浅复制
- 为了达到深复制,对象的引用,以及其引用的引用(依次类推)都需要实现深复制