重新學習了一遍java中的克隆,感覺原來學的太膚淺了,好多特性沒有了解到。
重新總結一遍:
1.java中的克隆對應設計模式中的prototype pattern。
2.如果一個對象想要被克隆,需要實現java.lang.Cloneable接口,這個接口和java.io.Serializable接口相似,都是不包含任何方法的接口,用來進行標志。
3.實現Cloneable接口後,需要覆蓋Object類中的clone方法,是Object中的一個native方法,需要注意的是Object本身並沒有實現Cloneable接口,所以不能對Object對象進行clone。
4.克隆分為shallow copy和deep copy
1、淺復制(淺克隆)
概念:被復制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用仍然指向原來的對象。換言之,淺復制僅僅復制所考慮的對象,而不復制它所引用的對象。
方法:類implements Cloneable,然後重寫clone()方法,在clone()方法中調用super.clone()即可,沒有其他操作了
2、深復制(深克隆)
概念:被復制對象的所有變量都含有與原來的對象相同的值,除去那些引用其他對象的變量。那些引用其他對象的變量將指向被復制過的新對象,而不再是原有的那些被引用的對象。換言之,深復制把要復制的對象所引用的對象都復制了一遍
方法:
(1)類implements Cloneable,然後重寫clone()方法,在clone()方法中調用super.clone(),然後還要對引用型變量所指的對象進行克隆。
(2)序列化:將該對象寫出到對象輸出流,那麼用對象輸入流讀回的對象就是原對象的一個深度克隆
5.java文檔上推薦的克隆的實現標准
The general intent is that, for any object x, the expression:
will be true, and that the expression:x.clone() != x
will be true, but these are not absolute requirements. While it is typically the case that:x.clone().getClass() == x.getClass()
will be true, this is not an absolute requirement.x.clone().equals(x)
1) 克隆新生成了一個對象,所以引用不同。
2) 克隆的對象與原來的對象是相同的類型,所以getClass應該相同。
3) 按照java的規范,在調用一個對象的equals方法前,這個對象應該已經重寫了equals方法,這樣比較的不僅僅是引用,所以這裡指的是兩個對象的信息是否相同,克隆出來的對象信息當然相同,所以這裡應該為true。
6.記一下今天寫的測試代碼
重寫Dog類的equals方法,仿照String類寫的
PS:要想知道clone真正的用武之地還得在實際中。
又看了一眼Integer的toString方法,Dog的equals方法還可以優化,改為
寫完了又發現這篇文章有2個嚴重的錯誤,弄巧成拙最後測試結果對了,不在文章上直接改,為了能牢記錯誤~。
1.String name是引用,所以在淺克隆的時候name僅僅是復制的引用。
2.在equals方法中,比較兩個String是用的==比較的,好久沒有這種錯誤了。
正好name復制的是引用,所以 == 還是返回的true。
改正:
String類型還有些不同,見 http://www.linuxidc.com/Linux/2011-10/44936.htm