經常有人會把引用拷貝理解為淺拷貝
1 dog dog1 = new dog();
2 dog dog2 = dog1;
這其實只是乙個賦值操作,把dog1的值賦值給了dog2,他們指向的其實是同乙個物件,這種情況屬於引用拷貝,通常意義上的深拷貝和淺拷貝都指的是物件拷貝
淺拷貝:
原型物件和複製出來的新物件,他們的引用型別的屬性如果位址值相同則是淺拷貝淺拷貝需要實現cloneable介面,cloneable其實是個空介面,相當於乙個標記(和serializable介面一樣),重寫clone方法,裡面呼叫父類的clone方法即可(呼叫的是object的clone方法)。
1
public
class
dogimplements
cloneable
16}
通過呼叫clone方法拷貝的物件你會發現是重新建立了乙個物件,但是物件裡面的引用型別的熟悉指向的還是同乙個位址(dog1和dog2指向的位址不同,dog1和dog2中的dogowner指向的位址相同)
1 dog dog1 = new dog();
2 dog1.setage(5);
3 dogowner dogowner = new dogowner();
4 dog1.setowner(dogowner);
5 dog dog2 = (dog) dog1.clone();
6 system.out.println("dog1是否等於dog2: "+(dog1 == dog2));
7 system.out.println("dog1中的owner是否等於dog2中的owner: "+(dog1.getowner() == dog2.getowner()));
深拷貝:
原型物件和複製出來的新物件,他們的所有屬性的位址值都是不同的深拷貝的實現方式有很多種,常見方式就是通過序列化和反序列化、轉json字串在轉成物件(其實原理類似)
我們以序列化為例:首先dog類和dogowner類都實現serializable介面,然後通過序列化和反序列化操作得到新的物件,我們會發現dog物件和裡面的引用型別的屬性指向的位址都不同,此時就是完成了深拷貝
1 dog dog1 = new dog();
2 dog1.setage(5);
3 dogowner dogowner = new dogowner();
4 dog1.setowner(dogowner);56
//將物件序列化到二進位製流
7 bytearrayoutputstream bos = new bytearrayoutputstream();
8 objectoutputstream oos = new objectoutputstream(bos);
9 oos.writeobject(dog1);
1011
//從二進位製流中讀出產生的新物件
12 bytearrayinputstream bis = new bytearrayinputstream(bos.tobytearray());
13 objectinputstream ois = new objectinputstream(bis);
14 dog dog2 = (dog)ois.readobject();
1516 system.out.println("dog1是否等於dog2: " + (dog1 == dog2));
17 system.out.println("dog1中的owner是否等於dog2中的owner: " + (dog1.getowner() == dog2.getowner()));
「淺拷貝」與「深拷貝」
c 中物件的複製就如同 轉殖 用乙個已有的物件快速地複製出多個完全相同的物件。一般而言,以下三種情況都會使用到物件的複製 1 建立乙個新物件,並用另乙個同類的已有物件對新物件進行初始化,例如 cpp view plain copy class rect rect rect1 rect rect2 r...
淺拷貝與深拷貝
淺拷貝 1 2 myclass a,b a b 為了封裝性和解耦,同型別的兩個物件之間進行賦值操作時,所有成員變數被複製,包括私有成員 指標變數。類的成員函式在傳遞或返回物件時都會進行物件複製產生臨時物件,比如函式呼叫時實參變為形參,以及函式返回物件。考慮到效能和使用者要求不同,編譯器不複製物件內部...
「淺拷貝」與「深拷貝」
c 中物件的複製就如同 轉殖 用乙個已有的物件快速地複製出多個完全相同的物件。一般而言,以下三種情況都會使用到物件的複製 1 建立乙個新物件,並用另乙個同類的已有物件對新物件進行初始化,例如 cpp view plain copy class rect rect rect1 rect rect2 r...