對象的克隆
1、克隆即復制的意思,對象的克隆,意味著生成一個對象,這個對象和某個對象的屬性和行為是一致的,但是這個對象和源對象是兩個不同的對象。實現對象的克隆,方法是實現Cloneable接口,否則會報異常CloneNotSupportedException
1 public class Demo implements Cloneable{ 2 private int number; 3 private String name; 4 5 public int getNumber() { 6 return number; 7 } 8 public void setNumber(int number) { 9 this.number = number; 10 } 11 public String getName() { 12 return name; 13 } 14 public void setName(String name) { 15 this.name = name; 16 } 17 18 19 public static void main(String[] args) { 20 Demo demo = new Demo(); 21 Demo demo2 = null; 22 try { 23 demo2 = (Demo) demo.clone(); 24 System.out.println(demo==demo2); 25 26 } catch (CloneNotSupportedException e) { 27 e.printStackTrace(); 28 } 29 } 30 }
輸出:
false
從結果我們可以知道,兩個引用指向的對象是兩個不同的Demo對象.
2、淺克隆
淺克隆是指在克隆對象的時候,對于對象中的屬性的值進行復制,那么這里引出一個問題,如對象的成員變量不論是基本類型還是引用類型,克隆對象的成員變量的值與源對象一致,這里引出一個問題,當成員變量是引用類型的時候,克隆對象和源對象的引用成員類型變量指向的是同一個對象,那么當這個對象本身的內容發生改動的時候,勢必影響到克隆對象和源對象,這樣在實際的生產過程可能帶來巨大問題。因此對象的克隆只在特定的場景下使用。
淺克隆的例子:
1 public class Demo implements Cloneable{ 2 private int number; 3 private Person person; 4 public int getNumber() { 5 return number; 6 } 7 public void setNumber(int number) { 8 this.number = number; 9 } 10 public Person getPerson() { 11 return person; 12 } 13 public void setPerson(Person person) { 14 this.person = person; 15 } 16 17 public static void main(String[] args) { 18 Demo demo = new Demo(); 19 demo.setNumber(10); 20 Person person = new Person(); 21 person.setName("test"); 22 demo.setPerson(person); 23 Demo demo2 = null; 24 try { 25 demo2 = (Demo) demo.clone(); 26 //很明顯,源對象和克隆對象的引用類型變量指向同一個Person對象 27 System.out.println(demo.getPerson()==demo2.getPerson()); 28 System.out.println(demo.getPerson().getName()+":"+demo2.getPerson().getName()); 29 //person對象發生變動 30 person.setName("demo"); 31 System.out.println(demo.getPerson().getName()+":"+demo2.getPerson().getName()); 32 33 } catch (CloneNotSupportedException e) { 34 e.printStackTrace(); 35 } 36 } 37 } 38 39 class Person{ 40 private String name; 41 42 public String getName() { 43 return name; 44 } 45 public void setName(String name) { 46 this.name = name; 47 } 48 }
輸出結果:
true test:test demo:demo
3、深克隆
在克隆時引用類型的變量在源對象和克隆對象中指向同一個對象。那么能否做到克隆出來的對象的引用屬性指向的對象與源對象是兩個不同的對象呢?答案是可以的,這種克隆被稱為深克隆。與淺克隆區別在于,復制對象的時候,是否對源對象中的引用變量指向的對象進行拷貝。進行深克隆的常用的手段是通過流和序列化/反序列化來實現。
1 public class Demo implements Serializable{ 2 private int number; 3 private Person person; 4 public int getNumber() { 5 return number; 6 } 7 public void setNumber(int number) { 8 this.number = number; 9 } 10 public Person getPerson() { 11 return person; 12 } 13 public void setPerson(Person person) { 14 this.person = person; 15 } 16 17 public static void main(String[] args){ 18 Demo demo = new Demo(); 19 demo.setNumber(10); 20 Person person = new Person(); 21 person.setName("test"); 22 demo.setPerson(person); 23 Demo demo2 = ObjectUtil.clone(demo); 24 System.out.println(demo.getPerson()==demo2.getPerson()); 25 System.out.println(demo.getPerson().getName()+":"+demo2.getPerson().getName()); 26 //person對象發生變動 27 person.setName("demo"); 28 System.out.println(demo.getPerson().getName()+":"+demo2.getPerson().getName()); 29 } 30 } 31 32 class Person implements Serializable{ 33 private String name; 34 35 public String getName() { 36 return name; 37 } 38 public void setName(String name) { 39 this.name = name; 40 } 41 }
工具類:
1 public class ObjectUtil { 2 @SuppressWarnings("unchecked") 3 public static <T>T clone(T obj){ 4 T clonedObj = null; 5 try { 6 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 7 //將對象寫進字節流中 8 ObjectOutputStream oos = new ObjectOutputStream(baos); 9 oos.writeObject(obj); 10 //從字節流中讀出對象 11 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); 12 ObjectInputStream ois = new ObjectInputStream(bais); 13 clonedObj = (T)ois.readObject(); 14 }catch (IOException e) { 15 e.printStackTrace(); 16 }catch (ClassNotFoundException e) { 17 e.printStackTrace(); 18 } 19 return clonedObj; 20 } 21 }
?