Java Clone 學(xué)習(xí)
原文地址:詳解Java中的clone方法
通常在Java中我們通過new關(guān)鍵字創(chuàng)建對象泰涂,代碼如下:
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
從結(jié)果看出human2和human指向了同一對象虐呻,從這行代碼頁印證了引用即是Java種的指針這一說法藻三。
Java中創(chuàng)建對象的方法有很多垫竞,常見的有:
- new 使用new關(guān)鍵字首先為新對象創(chuàng)建內(nèi)存透揣,然后使用構(gòu)造函數(shù)為新對象的各個(gè)Field初始化
- clone 首先為新對象創(chuàng)建內(nèi)存疏哗,然后使用舊的對象的值填充新的對象的各個(gè)Field
- readobject 首先為新對象創(chuàng)建內(nèi)存疲迂,從流中讀取數(shù)據(jù)若未,并填充新對象的各個(gè)Field
Clone 方法
Clone 定義在Object類中的保護(hù)方法朱嘴,一個(gè)類如果要支持Clone,需要按照下面的兩個(gè)步驟編寫代碼粗合。
- 重寫Clone方法
- 實(shí)現(xiàn)Cloneable接口 - Cloneable是一個(gè)標(biāo)記接口萍嬉,實(shí)現(xiàn)這個(gè)接口只需要在頂一類是聲明即可,如果類未實(shí)現(xiàn)Cloneable接口隙疚,調(diào)用其Clone方法會(huì)拋出CloneNotSupportedException
一個(gè)例子:
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");
}
}
運(yùn)行結(jié)果為:
human is :TestClone$Human@6d06d69c
human2 is :TestClone$Human@7852e922
從運(yùn)行結(jié)果看壤追,Clone方法創(chuàng)建了新的對象。
深復(fù)制和淺復(fù)制
淺復(fù)制
淺復(fù)制是指為新的對象創(chuàng)建內(nèi)存甚淡,并使用舊的對象的中的引用的值填充新的對象中引用的值大诸,觀察如下代碼:
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");
}
}
運(yùn)行結(jié)果:
human1 is :TestClone$Human@6d06d69c
human2 is :TestClone$Human@7852e922
human1 head is :TestClone$Head@4e25154f
human2 head is :TestClone$Head@4e25154f
從運(yùn)行結(jié)果看,Object類中Clone方法的實(shí)現(xiàn)為淺復(fù)制
深復(fù)制
深復(fù)制是指贯卦,為新的對象申請內(nèi)存资柔,并未其中的每個(gè)引用申請內(nèi)存。將上述的代碼改造如下:
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");
}
}
結(jié)果如下:
human1 is :TestClone$Human@6d06d69c
human2 is :TestClone$Human@7852e922
human1 head is :TestClone$Head@4e25154f
human2 head is :TestClone$Head@70dea4e
從結(jié)果看human和head都指向了新的對象(內(nèi)存)撵割。
繼續(xù)改造上述代碼:
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");
}
}
運(yùn)行結(jié)果如下:
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
從結(jié)果看face又指向了相同對象(引用)贿堰,為了完成徹底的深復(fù)制,需要對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;
}
}
結(jié)果如下:
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
結(jié)論
- Object類提供了Clone方法用于復(fù)制對象,
- 一個(gè)類如果要支持Clone啡彬,需要重寫Clone方法羹与,并實(shí)現(xiàn)Cloneable接口
- Object類的Clone實(shí)現(xiàn)為淺復(fù)制
- 為了達(dá)到深復(fù)制,對象的引用庶灿,以及其引用的引用(依次類推)都需要實(shí)現(xiàn)深復(fù)制