目錄
對象的克隆
克隆的做用
克隆的分類
克隆的使用
淺克隆的使用
深度克隆的使用
深度克隆的實現方式
總結java
java當中的克隆跟生物上所說的克隆相似,就是複製出一個如出一轍的個體,固然遷移到java當中,那就是複製出一個如出一轍對象,別忘了java當中有句話叫作一切皆對象。經過克隆就能提升對象的獨立性,使用起來更加方便,也更安全。安全
對象克隆主要是爲了解決引用類型在進行等號賦值時使得兩個引用同時指向同一個對象實例,從而致使經過兩個引用去操做對象時,會直接更改實例中的屬性破壞對象的相互獨立性。ide
//例如一下代碼段 public class Test { public static void main(String[] args) { // TODO Student s1 = new Student("Tom", 12); Student s2 = s1;//s2的引用指向s1 System.out.println(s1); System.out.println(s2); s2.setName("Jerry");//修改s2的值時s1的屬性 System.out.println(s1); System.out.println(s2); }
上述代碼運行的結果如圖:
this
由上述運行結果可知,在引用類型當中,因爲都是指向同一個對象實例,當咱們用引用類型去修改對象實例的值時,原來對象的屬性也會跟着改變,從而致使了數據的不一致性。對象的克隆就能解決上述問題,防止發生此類狀況。spa
淺克隆以下圖所示,只適用於基本的數據類型,對於值傳遞就只是賦值,把全部屬性都拿過來賦值給當前對象。當要克隆的對象裏面存在另一個非基本數據類型的對象實例時,因爲只是簡單地經過等號賦值,又至關於指向的是同一個實例對象,在進行修改時一樣會修改原來的屬性。
3d
而深度克隆就是把對象的全部屬性都通通複製一份新的到目標對象裏面去,使他成爲一個獨立的對象,當修改新的對象實例的屬性時,原來對象中的屬性任然不變。
code
淺克隆的實現代碼,例如:對象
package com.vince; //實現Cloneable接口 public class Product implements Cloneable{ private String name; private Integer price; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getPrice() { return price; } public void setPrice(Integer price) { this.price = price; } public Product(String name, Integer price) { super(); this.name = name; this.price = price; } @Override public String toString() { return "Product [name=" + name + ", price=" + price + "]"; } //重寫clone的方法 @Override public Product clone() { Product product = null; try { product = (Product)super.clone(); } catch (CloneNotSupportedException e) { product = null; e.printStackTrace(); } return product; } }
package com.vince; public class Test { public static void main(String[] args) { // TODO 對象的克隆 Product product1 = new Product("籃球", 189); // 1.在Product實現CoCloneable接口 // 2.重寫clone方法 Product product2 = product1.clone(); System.out.println(product2); product2.setPrice(200);//籃球漲價了 System.out.println(product1);//此時修改product2不會影響product1的值 System.out.println(product2); } }
深度克隆的實現代碼,例如:blog
package com.vince; //實現Cloneable接口 public class Product implements Cloneable{ private String name; private Integer price; public Shop shop; public Product(String name, Integer price, Shop shop) { this.name = name; this.price = price; this.shop = shop; } public Shop getShop() { return shop; } public void setShop(Shop shop) { this.shop = shop; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getPrice() { return price; } public void setPrice(Integer price) { this.price = price; } public Product(String name, Integer price) { super(); this.name = name; this.price = price; } @Override public String toString() { return "商店名:" + "\t" +name + "價格:" +"\t"+ price + "商店:" + shop; } //重寫clone的方法 @Override public Product clone() { Product product = null; try { // clone 的過程,new一個新的對象,將原對象中的屬性徹底複製(賦值) product = (Product)super.clone(); // Product中的Shop實例克隆獲得的對象 shop = (Shop)product.getShop().clone(); // 將新獲得的克隆對象覆蓋掉原來shop的屬性值 product.setShop(shop); } catch (CloneNotSupportedException e) { product = null; e.printStackTrace(); } return product; } }
package com.vince; public class Shop implements Cloneable{ private String name; private String address; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Shop(String name, String address) { super(); this.name = name; this.address = address; } @Override public String toString() { return "Shop [name=" + name + ", address=" + address + "]"; } @Override protected Shop clone() { Shop shop = null; try { shop = (Shop)super.clone(); } catch (CloneNotSupportedException e) { shop = null; e.printStackTrace(); } return shop; } }
深度克隆的第一種方式:若是被克隆對象中出現引用類型的變量(用戶自定義變量),須要手動再次進行克隆。
缺點:若是類與類之間的關聯關係較爲複雜時,逐層實現克隆較爲繁瑣
深度克隆的第二種方式:若是被克隆對象中出現引用類型的變量(用戶自定義變量),用序列化的方式實現克隆。序列化將在下一篇介紹。接口
對象的克隆主要是爲了解決在引用類型賦值時,經過引用類型賦值時修改屬性值時所形成的修改後的數據不一致的問題;克隆分爲淺克隆和深克隆,淺克隆只是適用於基本的數據類型,而對於非基本數據類型的任然不實用,一樣修改時會存在破壞對象之間的獨立性(如上述深克隆的使用中的例子,當Product中存在另一個自定義類型Shop時,經過克隆後修改shop的屬性任然會修改原來shop的屬性值);深度克隆是把每個對象都new一份到新的目標對象中,在要克隆的對象裏面嵌套的非基本的數據類型和自定義對象都要進行克隆或者實現克隆的接口,當層次變多時實現起來就比較繁瑣。還有最重要的一點是,全部的對象要想實現克隆,都必需要實現Cloneable方法和重寫clone()方法。
附語 因爲本人知識有限,若發現錯誤,但願你們可以批評和指正,謝謝