1. 程式人生 > >Java Object物件之clone方法

Java Object物件之clone方法

原文:http://blog.csdn.net/bigconvience/article/details/25025561

克隆的目的:快速建立一個已有物件的副本。

克隆的步驟:

  1. 建立一個物件
  2. 將原有物件的資料匯入到新建立的資料中

1. Object的clone()原始碼簡介

  1. /** 
  2.  * Creates and returns a copy of this {@code Object}. The default 
  3.  * implementation returns a so-called "shallow" copy: It creates a new 
  4.  * instance of the same class and then copies the field values (including
     
  5.  * object references) from this instance to the new instance. A "deep" copy, 
  6.  * in contrast, would also recursively clone nested objects. A subclass that 
  7.  * needs to implement this kind of cloning should call {@code super.clone()} 
  8.  * to create the new instance and then create deep copies of the nested,
     
  9.  * mutable objects. 
  10.  * 
  11.  * @return a copy of this object. 
  12.  * @throws CloneNotSupportedException 
  13.  *             if this object's class does not implement the {@code 
  14.  *             Cloneable} interface. 
  15.  */
  16. protected Object clone() throws CloneNotSupportedException {  
  17.     if (!(thisinstanceof Cloneable)) {  
  18.         thrownew CloneNotSupportedException("Class doesn't implement Cloneable");  
  19.     }  
  20.     return internalClone((Cloneable) this);  
  21. }  
  22. /* 
  23.  * Native helper method for cloning. 
  24.  */
  25. privatenative Object internalClone(Cloneable o);  

clone方法首先會判物件是否實現了Cloneable介面,若無則丟擲CloneNotSupportedException, 最後會呼叫internalClone. intervalClone是一個native方法,一般來說native方法的執行效率高於非native方法。

當某個類要複寫clone方法時,要繼承Cloneable介面。通常的克隆物件都是通過super.clone()方法來克隆物件。

2.淺克隆(shadow clone)

   克隆就是複製一個物件的複本.若只需要複製物件的欄位值(對於基本資料型別,如:int,long,float等,則複製值;對於複合資料型別僅複製該欄位值,如陣列變數則複製地址,對於物件變數則複製物件的reference。

例子:

  1. publicclass ShadowClone implements Cloneable{  
  2.     privateint a;   // 基本型別
  3.     privateint[] b; // 非基本型別
  4.     // 重寫Object.clone()方法,並把protected改為public
  5.     @Override
  6.     public Object clone(){  
  7.         ShadowClone sc = null;  
  8.         try
  9.         {  
  10.             sc = (ShadowClone) super.clone();  
  11.         } catch (CloneNotSupportedException e){  
  12.             e.printStackTrace();  
  13.         }  
  14.         return sc;  
  15.     }  
  16.     publicint getA()  
  17.     {  
  18.         return a;  
  19.     }  
  20.     publicvoid setA(int a)  
  21.     {  
  22.         this.a = a;  
  23.     }  
  24.     publicint[] getB() {  
  25.     return b;  
  26.     }  
  27.     publicvoid setB(int[] b) {  
  28.     this.b = b;  
  29.     }    
  30. }  
然後進行測試:
  1. publicclass Test{  
  2.     publicstaticvoid main(String[] args) throws CloneNotSupportedException{  
  3.         ShadowClone c1 = new ShadowClone();  
  4.         //對c1賦值
  5.         c1.setA(100) ;  
  6.         c1.setB(newint[]{1000}) ;  
  7.         System.out.println("克隆前c1:  a="+c1.getA()+" b="+c1.getB()[0]);  
  8.         //克隆出物件c2,並對c2的屬性A,B,C進行修改
  9.         ShadowClone c2 = (ShadowClone) c1.clone();  
  10.         //對c2進行修改
  11.         c2.setA(50) ;  
  12.         int []a = c2.getB() ;  
  13.         a[0]=5 ;  
  14.         c2.setB(a);  
  15.         System.out.println("克隆前c1:  a="+c1.getA()+" b="+c1.getB()[0]);  
  16.         System.out.println("克隆後c2:  a="+c2.getA()+ " b[0]="+c2.getB()[0]);  
  17.     }  
  18. }  
結果為:

克隆前c1:  a=100 b=1000
克隆前c1:  a=100 b=5
克隆後c2:  a=50 b[0]=5


c1和c2的物件模型:

                                                                     

可以看出,基本型別可以使用淺克隆,而對於引用型別,由於引用的是內容相同,所以改變c2例項物件中的屬性就會影響到c1。所以引用型別需要使用深克隆。另外,在開發一個不可變類的時候,如果這個不可變類中成員有引用型別,則就需要通過深克隆來達到不可變的目的。

3.深克隆(deep clone)

    深克隆與淺克隆的區別在於對複合資料型別的複製。若物件中的某個欄位為複合型別,在克隆物件的時候,需要為該欄位重新建立一個物件。

例子:

  1. publicclass DeepClone implements Cloneable {  
  2.     privateint a;   // 基本型別
  3.     privateint[] b; // 非基本型別
  4.     // 重寫Object.clone()方法,並把protected改為public
  5.     @Override
  6.     public Object clone(){  
  7.         DeepClone sc = null;  
  8.         try
  9.         {  
  10.             sc = (DeepClone) super.clone();  
  11.             int[] t = sc.getB();  
  12.             int[] b1 = newint[t.length];  
  13.             for (int i = 0; i < b1.length; i++) {  
  14.                 b1[i] = t[i];  
  15.             }  
  16.             sc.setB(b1);  
  17.         } catch (CloneNotSupportedException e){  
  18.             e.printStackTrace();  
  19.         }  
  20.         return sc;  
  21.     }  
  22.     publicint getA()  
  23.     {  
  24.         return a;  
  25.     }  
  26.     publicvoid setA(int a)  
  27.     {  
  28.         this.a = a;  
  29.     }  
  30.     publicint[] getB() {  
  31.         return b;  
  32.     }  
  33.     publicvoid setB(int[] b) {  
  34.         this.b = b;  
  35.     }  
  36. }  

結果為:

克隆前c1:  a=100 b=1000

克隆前c1:  a=100 b=1000
克隆後c2:  a=50 b[0]=5


物件模型:

                                        

4、總結:

  1. 克隆方法用於建立物件的拷貝,為了使用clone方法,類必須實現java.lang.Cloneable介面重寫protected方法clone,如果沒有實現Clonebale介面會丟擲CloneNotSupportedException.
  2. 在克隆java物件的時候不會呼叫構造器
  3. java提供一種叫淺拷貝(shallow copy)的預設方式實現clone,建立好物件的副本後然後通過賦值拷貝內容,意味著如果你的類包含引用型別,那麼原始物件和克隆都將指向相同的引用內容,這是很危險的,因為發生在可變的欄位上任何改變將反應到他們所引用的共同內容上。為了避免這種情況,需要對引用的內容進行深度克隆。


相關推薦

Java Object物件clone方法

原文:http://blog.csdn.net/bigconvience/article/details/25025561 克隆的目的:快速建立一個已有物件的副本。 克隆的步驟: 建立一個物件將原有物件的資料匯入到新建立的資料中 1. Object的clone()原始

Object物件clone方法

克隆的目的:快速建立一個已有物件的副本。克隆的步驟:建立一個物件將原有物件的資料匯入到新建立的資料中1. Object的clone()原始碼簡介 /** * Creates and returns a copy of this {@code Object}. The default *

Java 面向物件構造方法

01構造方法引入   A:構造方法的引入     在開發中經常需要在建立物件的同時明確物件的屬性值,比如員工入職公司就要明確他的姓名、年齡等屬性資訊。     那麼,建立物件就要明確屬性值,那怎麼解決呢?也就是在建立物件的時候就要做的事情,當使用new關鍵字建立物件時,怎麼給物件的屬性初始化值呢?     這

Java面向物件構造方法

package com.zhangxueliang.demo; /* * 構造方法: * 給物件的資料進行初始化 * * 格式: * 方法名和類名相同 *

11.JAVA-Objectfinalize(),clone(),toString()等方法覆寫

href this 都是 .html rac 回收 信息 ktr font 1.Object介紹 Object類是一個特殊的類,是所有類(包括數組,接口 )的父類,如果一個類沒有用extends明確指出繼承於某個類,那麽它默認繼承Object類,所以可以通過向上轉型的方法

java面向物件方法

面向物件-方法 課堂內容: 1.方法的概念 2.方法的定義 3.方法的分類 4.方法的過載 一、方法概念 方法的概念: ​ 方法是體現了面向物件中的封裝,將多個程式碼片段封裝成一個方法,為了這些程式碼的重用。 二、方法的定義: ​ [作用域/可見度

javaclone方法的使用

首先看一下jdk中對clone方法的解釋: 大概意思是說:返回一個要克隆物件的副本,克隆的型別依賴被克隆物件,換句話說:克隆後的物件型別與被克隆物件的型別相同。 一、簡單用法 只需要在需要clone的物件上實現(implements)Cloneable介面,然後再在類中加

JVM系列:詳解java object物件在heap中的結構

[toc] # 簡介 在之前的文章中,我們介紹了使用JOL這一神器來解析java類或者java例項在記憶體中佔用的空間地址。 今天,我們會更進一步,剖析一下在之前文章中沒有講解到的更深層次的細節。一起來看看吧。 # 物件和其隱藏的祕密 java.lang.Object大家應該都很熟悉了,Object

java設計模式模板方法模式

java 設計模式宋丹丹姐的一個小品,說把大象放入冰箱分為幾步驟,三步、第一步:把冰箱門打開,第二步:把大象裝進去,第三步:把冰箱門關上。就是這樣的一個小品,可以說是其實簡化的一個模板方法。把雞蛋裝進冰箱分為幾步,同樣也是這個道理。模板方法模式概念:把一些共同的行為抽象出來,作為父類公共使用,一些具體的步驟

Java Object類及其equals方法

str div tag 概念 == OS object span post 基本概念: Object類位於java.lang包中,java.lang包包含著Java最基礎和核心的類,在編譯時會自動導入; Object類是所有Java類的祖先。每個類都使用 Objec

Java Object類的equals()方法

幫助 ati pac obj nbsp 就是 pre 如果 是否 所有類都從Object類中繼承了equals方法,Object類中equals方法源代碼如下: public boolean equals(Object obj) { return

Java面對物件封裝

學習到了封裝,也希望這篇文章能個給後面學習java的人一點幫助.   首先我們用實際問題先感受一下封裝的概念.   用人來舉例,人的年齡是有限的,0-120左右   我們在社交網站填寫個人資訊的時候,也會有年齡這一項,那麼這個年齡允許填寫負數或者很大的數嗎?   實際上是不允許的.   

Java面向物件——類與方法

面向物件——能進行現實生活的抽象 世界是由一系列物件互相組合形成(多個物件之間的相互協作),每個物件有自己的屬性和方法。 通俗解釋:狗吃糧,狗和糧是兩個物件 ,吃是行為 每個物件——類,每個類有自己的屬性及方法 新興的程式設計正規化: 面向切面程式設計:EE-AOP 面向介面

Java 設計模式工廠方法模式與抽象工廠模式

一、前期回顧 上一篇《Java設計模式之單例模式》詳細介紹了單例模式,介紹了單例模式的使用場景,優缺點,同時也寫了兩種常見的單例模式寫法,懶漢式單例模式和餓漢氏單例模式,當然,單例模式的寫法還有很多,比如,列舉單例模式,靜態內部類單例模式等。有興趣的可以自行查詢資料。本篇開始介紹單例

Java設計模式模板方法(Template Method)

模式定義 需求背景 具體實現 模式定義 模板方法: 定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中,模板方法使得子類可以不改變一個演算法的結構

JAVA---面向物件從生活中抽取例項物件

public class Car{ private String brand; private int num; private String colour; private int seats; //建構函式 public Car(String brand){

Java面向物件多型(向上轉型與向下轉型)

多型,大概每個人都知道。但是,又有幾個人真的理解什麼是多型、多型有哪些細節呢?如果你看到這篇文章的名字,腦海中對多型沒有一個清晰的概念,不妨點進來看看,也許會有收穫。 什麼是多型 簡單的理解多型 多型,簡而言之就是同一個行為具有多個不同表現形式或形態的能力。比如說,有一杯水,我不知道

JAVA設計模式模板方法模式和建造者模式

一、前期回顧 上一篇《Java 設計模式之工廠方法模式與抽象工廠模式》介紹了三種工廠模式,分別是工廠方法模式,簡單工廠方法模式,抽象工廠模式,文中詳細根據實際場景介紹了三種模式的定義,實踐,最後總結了三種方式的區別,以及各個模式的適用場景。這一篇博文我們來學習下模板方法模式和建造者模式。

Java面向物件——類與方法(練習:將車抽象為類)

程式碼: public class Car{ //屬性 //品牌(不可更改)、產地(不可更改)、顏色、價格 private String brand; private String origin; private String colour; private int price;

ES6 Promise物件例項方法(2)

ES6 Promise物件之例項方法(2) 上一篇關於Promise的文章介紹了Promise的基本用法,這一篇繼續上一篇,介紹Promise的各種方法: (1)Promise.prototype.then() then方法是定義在原型物件Promise.prototype上的。