對象的copy你興許只是懵懂,或者是並沒在意,來了解下吧。
對於的github基礎代碼https://github.com/chywx/JavaSE
最近學習c++,跟java很是相像,在慕課網學習c++也算是重溫習了下java基礎
明白了當初講師一直強調java傳遞的話只有值傳遞,不存在引用傳遞,為什么一直要重復這,既然只有值傳遞,為啥還強調不是引用傳遞
毛病啊這是
學了c++才知道,原來c++有值傳遞,引用傳遞的說法,但是java只是值傳遞
最簡單的理解就是對於方法調用
比如 f(int a,int b) 這是值傳遞,傳遞過來的值不會被修改。
再如 f(int &a,int &b)這是引用傳遞,傳遞過來的值會被修改
步入正軌,說一說java的淺拷貝(Shallow Copy)、深拷貝(Deep Copy)。
淺拷貝(Shallow Copy):①對於數據類型是基本數據類型的成員變量,淺拷貝會直接進行值傳遞,也就是將該屬性值復制一份給新的對象。因為是兩份不同的數據,所以對其中一個對象的該成員變量值進行修改,不會影響另一個對象拷貝得到的數據。②對於數據類型是引用數據類型的成員變量,比如說成員變量是某個數組、某個類的對象等,那么淺拷貝會進行引用傳遞,也就是只是將該成員變量的引用值(內存地址)復制一份給新的對象。因為實際上兩個對象的該成員變量都指向同一個實例。在這種情況下,在一個對象中修改該成員變量會影響到另一個對象的該成員變量值。
通過示例來了解下,
一:
使用構造函數實現copy
public class Person { public static void main(String[] args) { Son s = new Son(10); Person p1 = new Person("大海", s); Person p2 = new Person(p1); p1.setSonName("小海"); p1.getSon().setAge(12); System.out.println("p1:" + p1);// p1:Person [sonName=小海, son=Son [age=10]]
System.out.println("p2:" + p2);// p2:Person [sonName=大海, son=Son [age=10]]
} private String sonName; private Son son; // 自定義拷貝函數
public Person(Person person) { this.sonName = person.sonName; this.son = person.son; } public Person(String sonName, Son son) { super(); this.sonName = sonName; this.son = son; } public String getSonName() { return sonName; } public void setSonName(String sonName) { this.sonName = sonName; } public Son getSon() { return son; } public void setSon(Son son) { this.son = son; } @Override public String toString() { return "Person [sonName=" + sonName + ", son=" + son + "]"; } } class Son { private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Son(int age) { super(); this.age = age; } @Override public String toString() { return "Son [age=" + age + "]"; } }
結果
p1:Person [sonName=小海, son=Son [age=12]]
p2:Person [sonName=大海, son=Son [age=12]]
對於上面的實例,該person對象有兩個成員,一個基本類型,一個引用類型,結果是拷貝出來的對象,基本類型的那個成員真正的實現了copy。
二:
使用自帶的clone方法,需要實現cloneable接口,不然會
Exception in thread "main" java.lang.CloneNotSupportedException:

public class Person2 implements Cloneable { public static void main(String[] args) throws CloneNotSupportedException { Son2 son1 = new Son2(10); Person2 person1 = new Person2("大海", son1); Person2 person2 = (Person2) person1.clone(); person2.setSon2Name("小海"); person2.getSon2().setAge(12); System.out.println(person1); System.out.println(person2); } public Person2(String son2Name, Son2 son2) { super(); this.son2Name = son2Name; this.son2 = son2; } private String son2Name; private Son2 son2; public String getSon2Name() { return son2Name; } public void setSon2Name(String son2Name) { this.son2Name = son2Name; } public Son2 getSon2() { return son2; } public void setSon2(Son2 son2) { this.son2 = son2; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return "Person2 [son2Name=" + son2Name + ", son2=" + son2 + "]"; } } class Son2 { private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Son2 [age=" + age + "]"; } public Son2(int age) { super(); this.age = age; } }
結果:
Person2 [son2Name=大海, son2=Son2 [age=12]]
Person2 [son2Name=小海, son2=Son2 [age=12]]
使用自帶的copy實現淺拷貝
---------------------------------------------------------------------------------------------------
深拷貝
相對於淺拷貝而言,對於引用類型的修改,並不會影響到對應的copy對象的值。每一層的每個對象都進行淺拷貝=深拷貝。
一:
還是使用clone方法,只不過得手動重寫一下。

上代碼
public class Person3 implements Cloneable { public static void main(String[] args) throws CloneNotSupportedException { Son3 son1 = new Son3(10); Person3 person1 = new Person3("大海", son1); Person3 person2 = (Person3) person1.clone(); person2.setSon2Name("小海"); person2.getSon3().setAge(12);//修改對應的引用對象的值。
System.out.println(person1); System.out.println(person2); } public Person3(String son2Name, Son3 son3) { super(); this.son2Name = son2Name; this.son3 = son3; } private String son2Name; private Son3 son3; public String getSon2Name() { return son2Name; } public void setSon2Name(String son2Name) { this.son2Name = son2Name; } public Son3 getSon3() { return son3; } public void setSon3(Son3 son3) { this.son3 = son3; } @Override protected Object clone() throws CloneNotSupportedException { Person3 clone = (Person3) super.clone(); clone.setSon3((Son3) clone.getSon3().clone()); return clone; } @Override public String toString() { return "Person3 [son2Name=" + son2Name + ", son3=" + son3 + "]"; } } class Son3 implements Cloneable { private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Son2 [age=" + age + "]"; } public Son3(int age) { super(); this.age = age; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
結果:
Person3 [son2Name=大海, son3=Son2 [age=10]]
Person3 [son2Name=小海, son3=Son2 [age=12]]
方法二:
顯然對於多個對象的話,顯然就很吃力。可以使用另一種方式,
將對象序列化為字節序列后,默認會將該對象的整個對象圖進行序列化,再通過反序列即可完美地實現深拷貝。

public class Person4 implements Serializable { public static void main(String[] args) throws CloneNotSupportedException, ClassNotFoundException, IOException { Son4 son = new Son4(10); Person4 person1 = new Person4("大海", son); //通過序列化方法實現深拷貝
ByteArrayOutputStream bos=new ByteArrayOutputStream(); ObjectOutputStream oos=new ObjectOutputStream(bos); oos.writeObject(person1); oos.flush(); ObjectInputStream ois=new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); Person4 person2=(Person4)ois.readObject(); person1.setSon4Name("小海"); person1.getSon4().setAge(12); System.out.println(person1.toString()); System.out.println(person2.toString()); } public Person4(String son4Name, Son4 son4) { super(); this.son4Name = son4Name; this.son4 = son4; } private String son4Name; private Son4 son4; public String getSon4Name() { return son4Name; } public void setSon4Name(String son4Name) { this.son4Name = son4Name; } public Son4 getSon4() { return son4; } public void setSon4(Son4 son4) { this.son4 = son4; } @Override public String toString() { return "Person4 [son4Name=" + son4Name + ", son4=" + son4 + "]"; } } class Son4 implements Serializable { private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Son2 [age=" + age + "]"; } public Son4(int age) { super(); this.age = age; } }
這是實現序列化接口方案,nice.
perfect!!!到位
記錄下聽得歌曲。
絕世
(張克帆)
世間種種的誘惑
不驚不擾我清夢
山高路遠不絕我
追蹤你絕美的笑容
登高一呼時才懂
始終在為你心痛
俯首對花影搖動
都是東風在捉弄
世間種種的迷惑
都是因你而猜錯
水光月光又交融
描述這朗朗的夜空
生死到頭的相從
似狂花落葉般從容
當一切泯滅如夢
就在遠山被絕世塵封
