紙上得來終覺淺,絕知此事要躬行
--陸遊 問渠那得清如許,為有源頭活水來 --朱熹
clone和Copy:當有一個物件Person p1=new Person("name",age );Person p2=p1;此時只是簡單的copy了一下引用,p1和p2都指向了內存中的同一個對象,修改p1和p2中任何一個都會影響到對方。 當函數的參數是物件時,傳遞的是參考類型,在物件函數內部的操作會影響到外邊物件。 如果希望傳遞的是物件的一個拷貝時,這時就需要用到object的clone()方法。 )拷貝對象返回的是一個新對象,而不是引用;拷貝對象與new操作符返回的新對象的區別就是這個拷貝對像已經包含了原來對象的一些信息,而不是對象的初始資訊。 什麼時候使用shallow Clone(淺拷貝,影子拷貝),什麼時候使用deep Clone(深拷貝):主要看具體域物件的性質是什麼,如果是基本類型使用shallow Clone,如果是reference variable(引用變數)使用deep Clone。
實作複製的步驟:
(1)實作Cloneable介面,Cloneable沒有任何抽象方法,稱為標誌介面。
(2)覆寫基底類別的clone方法,並宣告為public
(3)在衍生類別中重寫clone方法,並呼叫super.clone( )
在clone中分為淺拷貝和深拷貝,淺拷貝就是不管參數是基本型別還是引用型,直接呼叫super.clone()進行拷貝,結果參考型別還是指向相同的記憶體;深拷貝就是在呼叫super.clone()之後,也要呼叫引用參數的clone()函數,進行拷貝,來達到深拷貝。
淺拷貝:
(1) 基本的資料型別(String)是會拷貝複製一份新的物件
(2)引用物件還是引用同一份物件。
淺拷貝範例程式碼:
public class Info { public int idnumber; public int getIdnumber() { return idnumber; } public void setIdnumber(int idnumber) { this.idnumber = idnumber; } } public class Person implements Cloneable{ private int age; private String nameString; public Info info; public Info getInfo() { return info; } public void setInfo(Info info) { this.info = info; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getNameString() { return nameString; } public void setNameString(String nameString) { this.nameString = nameString; } public String toString() { return "name:"+nameString+",age:"+age+",idnumber"+info.idnumber; } public Object clone() { Person person=null; try { person=(Person)super.clone(); //浅拷贝 //person.info=(Info)info.clone(); } catch (CloneNotSupportedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } return person; } } public class Hello { public static void main(String[] args) { // TODO 自动生成的方法存根 Info info=new Info(); info.setIdnumber(100); Person person1=new Person(); person1.setAge(10); person1.setNameString("tiantian"); person1.info=info; Person person2=(Person)person1.clone(); person2.setNameString("hello"); person2.setAge(20); person2.info.setIdnumber(200); System.out.println("person2"+person2); System.out.println("person1"+person1); } }
最後的結果是:
person2name:hello,age:20,idnumber200 person1name:tiantian,age:10,idnumber200
person1和person2的基本型別name和age都改變了,但引用型別的idnumber數值沒變。
深拷貝:
(1)对存在的引用类型也进行拷贝,浅拷贝与深拷贝的代码还是有不同点的。
深拷贝代码示例:
public class Info implements Cloneable {//Info也进行拷贝 public int idnumber; public int getIdnumber() { return idnumber; } public void setIdnumber(int idnumber) { this.idnumber = idnumber; } public Object clone() { Info info=null; try { info=(Info)super.clone(); } catch (CloneNotSupportedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } return info; } } public class Person implements Cloneable{ private int age; private String nameString; public Info info; public Info getInfo() { return info; } public void setInfo(Info info) { this.info = info; } public Person() { // TODO 自动生成的构造函数存根 } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getNameString() { return nameString; } public void setNameString(String nameString) { this.nameString = nameString; } public String toString() { return "name:"+nameString+",age:"+age+",idnumber"+info.idnumber; } public Object clone() { Person person=null; try { person=(Person)super.clone(); //浅拷贝 person.info=(Info)info.clone();//加上这一句就变成了深拷贝,对对象引用也进行一次拷贝 } catch (CloneNotSupportedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } return person; } }
结果:
person2name:hello,age:20,idnumber200 person1name:tiantian,age:10,idnumber100
所有的值都进行了改变。
以上是Java-clone程式碼範例總結的詳細內容。更多資訊請關注PHP中文網其他相關文章!