謹慎的覆蓋clone(11)

一、Cloneable 接口的目的是代表對象時複製的數組

  • 沒達到目的的緣由是:缺乏clone方法

二、Object 的克隆方法是受保護的安全

  • 不借助於反射,僅僅實現Cloneable 接口是沒法調用clone 方法的
  •  

三、Cloneable 接口決定了,Object 中受保護的clone方法實現的行爲架構

  • 若是實現了Cloneable,Object 的clone 方法返回逐域拷貝
  • 不然,拋出CloneNotSupportedException 異常
  • 接口的極端非典型用法,不值得效仿
  • 一般狀況下,實現接口是爲了代表它能夠爲類作些什麼
  • Cloneable 接口改變了超類中受保護的方法的行爲
  • 實現了該接口,無需調用構造器就能夠建立對象

四、clone方法的通用約定很是弱ide

  • 拷貝的精確含義取決於,實現類自己
  • 通常意義上(但不是絕對):

  • 一般狀況下(但不是絕對)

  • 拷貝對象須要建立累的新實例
  • 並且須要拷貝內部結構

五、不調用構造器的規定太強硬this

  • 行爲良好的構造器能夠由構造器建立,再複製內部對象
  • 若是是final 類,甚至能夠是返回一個構造器建立的對象

六、x.clone().getClass()==x.getClass() 一般狀況下是true 線程

  • 在子類中調用super.clone(),返回的是子類的實例
  • 超類實現這種功能的惟一途徑是返回一個super.clone()返回的對象
  • 全部超類都遵照該規則,最後返回Object 的clone ,返回一個正確的實例(行爲良好clone 方法
  • 若是返回一個構造器建立的類,就獲得一個錯誤的實例

七、Object 的clone 方法是一個本地方法設計

  • Object 的clone 方法是一個本地方法
  • 執行的時候使用RTTI(run-time type identification)
  • 動態獲得正在調用clone方法的那個reference
  • 根據它的大小申請內存空間,而後進行bitwise的複製
  • 將該對象的內存空間徹底複製到新的空間中去,從而達到shallowcopy的目的
  • 獲得當前類的副本,不是父類
  • 根本沒有必用調用this.clone()

八、從超類的角度,拷貝對象是對原始對象功能的完整拷貝對象

  • 基本類型和不可變類,返回對象沒有問題,不須要進一步處理

永遠不要讓客戶去作類庫能夠提供的事情繼承

  • 若是帶有可變類,簡單的clone 實現可能帶來災難性後果
  • 下述Stack 類,若是採用簡單的clone ,elements僅僅是引用複製,新老引用指向同一個數組

clone 方法是類的另外一個構造器,確保不要傷害原有對象,確保正確建立被克隆對象全部約束條件遞歸

  • 最容易實現方法:

數組不須要 類型轉換,類型在編譯時與被克隆類型是相同的

九、若是可變類存在final 的域,上述方案不能正常運行:clone 方法會被禁止賦新值

  • clone 架構與引用可變對象的final 域之間自己就是衝突的
  • 去掉final 再clone

十、遞歸調用clone 有時還不夠

  • 例如:

  • 上述類,帶有內部類,須要複製每個對象(深度拷貝):
  • 遞歸調用式拷貝:

  • 遞歸調用針對鏈表中每一個元素,都消耗一段棧空間
  • 鏈表過長可能會溢出
  • 迭代式拷貝避免了上述狀況(迭代器能用就用啊):

  • clone 方法以下:

十一、克隆複雜對象的最後一種方法

  • 先調用super.clone 方法
  • 把全部域置空
  • 最後再把每一個值都填進去
  • 這是一種簡單、優美、合理的克隆方法
  • 運行效率比直接操做對象內部狀態要差

十二、clone 方法與構造器同樣,clone 方法在構造過程當中,不能調用新對象任何非 final 的方法

  • 新對象被拷貝出來前,不能調用它的非 final 方法

1三、覆蓋版本的clone 方法不該該忽略聲明可拋出異常 CloneNotSupportedException

  • Object 的clone 方法可拋出 CloneNotSupportedException 異常
  • 公有的覆蓋版本clone 方法可省略
  • 省略後使用更輕鬆

1四、專門爲繼承而設計的類<17條>,應儘可能模仿Object 的clone 方法

  • (protected、可拋出上述異常)
  • 不該該實現Cloneable 接口,繼承類可自由選擇是否實現Cloneable 接口
  • 這樣便直接擴展了Object

1五、線程安全的類實現 Cloneable 接口,clone 方法也必須同步

  • Object 的clone 沒有同步
  • 使用同步的clone 方法調用super.clone()

1六、不可變類不要提供拷貝方法

  • 倆對象沒區別,拷貝沒意義

1七、拷貝構造器(拷貝工廠)

  • 相似於靜態工廠:

優點:

  • 不依賴於有風險的、對象以外的對象建立機制
  • 不要求遵照還沒有指定好的文檔規範
  • 不會與 final 域的正常使用發生衝突
  • 不會拋出沒必要要的受檢異常
  • 不須要進行類型轉換
  • 採用拷貝構造器沒有放棄接口的功能特性(Cloneable 接口是一個空接口

1八、拷貝構造器(拷貝工廠)能夠帶有一個參數:

  • 參數類型是經過該類實現的接口
  • 實質就是轉換構造器(轉換工廠)
  • 好比HashSet 轉換成TreeSet:new TreeSet(s)
相關文章
相關標籤/搜索