對象的復制
阿新 • • 發佈:2018-07-16
有一個 getaddr get 一段 www ble 慎用 nbsp 轉載
先放一段代碼
Point.java
1 public class Point { 2 private int i; 3 4 public Point(int i) { 5 this.i = i; 6 } 7 8 public int getI() { 9 return i; 10 } 11 12 public void setI(int i) { 13 this.i = i; 14 } 15 }
PointTest.java
1 public class PointTest { 2 public static void main(String[] args) { 3 //創建一個Point對象,使用pa這個引用變量來指向它 4 Point pa = new Point(5); 5 //創建一個pb引用變量,將pa的值賦值給pb 6 Point pb = pa; 7 //改變pa中的屬性的值 8 pa.setI(3); 9 //顯示pb中的值 10 System.out.println(pb.getI());11 } 12 }
輸出的值為:3
因為pa和pb指向的是同一個對象(地址),改變其中任何一個都會改變該對象的內容。
那麽如何做到分開呢?就是改變pa的時候不讓pb發生改變(一般用於設置中間變量),這裏就涉及到對象的復制。
淺拷貝
將Point類修改為Point2類:
1 public class Point2 implements Cloneable { 2 private int i; 3 4 public Point2(int i) { 5 this.i = i; 6 } 7 8 publicint getI() { 9 return i; 10 } 11 12 public void setI(int i) { 13 this.i = i; 14 } 15 16 @Override 17 public Object clone() throws CloneNotSupportedException { 18 return super.clone(); 19 } 20 }
Point2Test.java
public class Point2Test { public static void main(String[] args) throws CloneNotSupportedException { //創建一個Point2對象,使用p2a這個引用變量來指向它 Point2 p2a = new Point2(5); //創建一個新對象,它是p2a的克隆,然後將這個新對象的引用賦值個p2b Point2 p2b = (Point2)p2a.clone(); //改變p2a中的屬性的值 p2a.setI(3); //顯示p2b中的值 System.out.println(p2b.getI()); } }
輸出的值為:5
p2a和p2b是內容相容的不同對象。
Object類中的clone方法將原始對象的每個數據域復制給目標對象:
1.如果一個數據域是基本類型,復制的就是它的值;
2.如果一個數據域是對象,那麽復制的就是它的引用。註意這裏是它的引用。
如果Point2類中有一個數據域Address類,那麽雖然p2a==p2b為假,但是p2a.address==p2b.address為真。
所以這稱之為淺拷貝。
深拷貝
Address類
1 public class Address implements Cloneable { 2 private String addressName; 3 4 public String getAddressName() { 5 return addressName; 6 } 7 8 public void setAddressName(String addressName) { 9 this.addressName = addressName; 10 } 11 12 @Override 13 public Object clone() throws CloneNotSupportedException { 14 return super.clone(); 15 } 16 }
Point3類
1 public class Point3 implements Cloneable { 2 private int i; 3 private Address address; 4 5 public Point3(int i) { 6 this.i = i; 7 } 8 9 public int getI() { 10 return i; 11 } 12 13 public void setI(int i) { 14 this.i = i; 15 } 16 17 public Address getAddress() { 18 return address; 19 } 20 21 public void setAddress(Address address) { 22 this.address = address; 23 } 24 25 @Override 26 public Object clone() throws CloneNotSupportedException { 27 Point3 p3 = null; 28 p3 = (Point3) super.clone(); 29 p3.address = (Address) address.clone(); 30 31 return p3; 32 } 33 }
Point3Test.java
1 public class Point3Test { 2 public static void main(String[] args) throws CloneNotSupportedException { 3 //初始化對象p3a 4 Point3 p3a = new Point3(5); 5 Address address = new Address(); 6 address.setAddressName("位置1"); 7 p3a.setAddress(address); 8 9 //復制對象 10 Point3 p3b = (Point3) p3a.clone(); 11 12 //改變p3a的address 13 address.setAddressName("位置2"); 14 15 //輸出結果比較 16 System.out.println("p3a的i: " + p3a.getI() + " p3a的address: " + 17 p3a.getAddress().getAddressName()); 18 System.out.println("p3b的i: " + p3b.getI() + " p3b的address: " + 19 p3b.getAddress().getAddressName()); 20 } 21 }
結果如圖:
結論:如果在拷貝一個對象時,要想讓這個拷貝的對象和源對象完全彼此獨立,那麽在引用鏈上的每一級對象都要被顯式的拷貝。所以創建徹底的深拷貝是非常麻煩的,尤其是在引用關系非常復雜的情況下。
所以有了如下一點,阿裏巴巴Java開發手冊第四章第19條:
【推薦】慎用 Object 的 clone 方法來拷貝對象。
說明: 對象的 clone 方法默認是淺拷貝,若想實現深拷貝需要重寫 clone 方法實現屬性對象的拷貝。
參考資料:
https://www.cnblogs.com/dolphin0520/p/3700693.html
https://blog.csdn.net/u014727260/article/details/55003402
本文系原創,轉載請註明出處,謝謝。
對象的復制