1. 程式人生 > >JAVA中淺複製與深複製

JAVA中淺複製與深複製

JAVA中淺複製深複製

1.淺複製與深複製概念
⑴淺複製(淺克隆)
被複制物件的所有變數都含有與原來的物件相同的值,而所有的對其他物件的引用仍然指向原來的物件。換言之,淺複製僅僅複製所考慮的物件,而不復制它所引用的物件。
 
⑵深複製(深克隆)
被複制物件的所有變數都含有與原來的物件相同的值,除去那些引用其他物件的變數。那些引用其他物件的變數將指向被複制過的新物件,而不再是原有的那些被引用的物件。換言之,深複製把要複製的物件所引用的物件都複製了一遍。
 
2.Java的clone()方法
⑴clone方法將物件複製了一份並返回給呼叫者。一般而言,clone()方法滿足:
①對任何的物件x,都有x.clone() !=x//克隆物件與原物件不是同一個物件
②對任何的物件x,都有x.clone().getClass()= =x.getClass()//克隆物件與原物件的型別一樣
③如果物件x的equals()方法定義恰當,那麼x.clone().equals(x)應該成立。
 
⑵Java中物件的克隆
①為了獲取物件的一份拷貝,我們可以利用Object類的clone()方法。
②在派生類中覆蓋基類的clone()方法,並宣告為public。
③在派生類的clone()方法中,呼叫super.clone()。
④在派生類中實現Cloneable介面。
 
請看如下程式碼:

class Student implements Cloneable
{
    String name;
    
int age;
    Student(String name,
int age)
    
{
        
this.name=name;
        
this.age=age;
    }

    
public Object clone()
    
{
        Object o
=null;
        
try
        
{
        o
=(Student)super.clone();//Object中的clone()識別出你要複製的是哪一個物件。
        }

        
catch(CloneNotSupportedException e)
        
{
            System.out.println(e.toString());
        }

        
return o;
    }


    
publicstaticvoid main(String[] args)
    
{
          Student s1
=new Student("zhangsan",18);
          Student s2
=(Student)s1.clone();
          s2.name
="lisi";
         s2.age
=20;
         System.out.println(
"name="+s1.name+","+"age="+s1.age);//修改學生2後,不影響學生1的值。
    }

}

 

 說明:
①為什麼我們在派生類中覆蓋Object的clone()方法時,一定要呼叫super.clone()呢?在執行時刻,Object中的clone()識別出你要複製的是哪一個物件,然後為此物件分配空間,並進行物件的複製,將原始物件的內容一一複製到新物件的儲存空間中。
②繼承自java.lang.Object類的clone()方法是淺複製。以下程式碼可以證明之。

class Professor 
{
    String name;
    
int age;
    Professor(String name,
int age)
    
{
        
this.name=name;
        
this.age=age;
    }

}

class Student implements Cloneable
{
    String name;
//常量物件。
int age;
    Professor p;
//學生1和學生2的引用值都是一樣的。
    Student(String name,int age,Professor p)
    
{
        
this.name=name;
        
this.age=age;
        
this.p=p;
    }

    
public Object clone()
    
{
        Student o
=null;
        
try
        
{
            o
=(Student)super.clone();
        }

        
catch(CloneNotSupportedException e)
        
{
            System.out.println(e.toString());
        }

        o.p
=(Professor)p.clone();
        
return o;
    }

    
publicstaticvoid main(String[] args)
    
{
          Professor p
=new Professor("wangwu",50);
          Student s1
=new Student("zhangsan",18,p);
          Student s2
=(Student)s1.clone();
          s2.p.name
="lisi";
         s2.p.age
=30;
    System.out.println(
"name="+s1.p.name+","+"age="+s1.p.age);//學生1的教授成為lisi,age為30。
    }

}

那應該如何實現深層次的克隆,即修改s2的教授不會影響s1的教授?程式碼改進如下。
 
改進使學生1的Professor不改變(深層次的克隆)

class Professor implements Cloneable
{
    String name;
    
int age;
    Professor(String name,
int age)
    
{
        
this.name=name;
        
this.age=age;
    }

    
public Object clone()
    
{
        Object o
=null;
        
try
        
{
            o
=super.clone();
        }

        
catch(CloneNotSupportedException e)
        
{
            System.out.println(e.toString());
        }

        
return o;
    }

}

class Student implements Cloneable
{
    String name;
    
int age;
    Professor p;
    Student(String name,
int age,Professor p)
    
{
        
this.name=name;
        
this.age=age;
        
this.p=p;
    }

    
public Object clone()
    
{
        Student o
=null;
        
try
        
{
            o
=(Student)super.clone();
        }

        
catch(CloneNotSupportedException e)
        
{
            System.out.println(e.toString());
        }

        o.p
=(Professor)p.clone();
        
return o;
    }

    
publicstaticvoid main(String[] args)
    
{
          Professor p
=new Professor("wangwu",50);
          Student s1
=new Student("zhangsan",18,p);
          Student s2
=(Student)s1.clone();
          s2.p.name
="lisi";
         s2.p.age
=30;
         System.out.println(
"name="+s1.p.name+","+"age="+s1.p.age);//學生1的教授不改變。
    }


}

 
3.利用序列化來做深複製
    把物件寫到流裡的過程是序列化(Serilization)過程,但是在Java程式師圈子裡又非常形象地稱為“冷凍”或者“醃鹹菜(picking)”過程;而把物件從流中讀出來的並行化(Deserialization)過程則叫做“解凍”或者“回鮮(depicking)”過程。應當指出的是,寫在流裡的是物件的一個拷貝,而原物件仍然存在於JVM裡面,因此“醃成鹹菜”的只是物件的一個拷貝,Java鹹菜還可以回鮮。
在Java語言裡深複製一個物件,常常可以先使物件實現Serializable介面,然後把物件(實際上只是物件的一個拷貝)寫到一個流裡(醃成鹹菜),再從流裡讀出來(把鹹菜回鮮),便可以重建物件。
如下為深複製原始碼。

public Object deepClone()
{
      
//將物件寫到流裡
      ByteArrayOutoutStream bo=new ByteArrayOutputStream();
      ObjectOutputStream oo
=new ObjectOutputStream(bo);
      oo.writeObject(
this);
      
//從流裡讀出來
      ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
      ObjectInputStream oi
=new ObjectInputStream(bi);
      
return(oi.readObject());
}

       這樣做的前提是物件以及物件內部所有引用到的物件都是可序列化的,否則,就需要仔細考察那些不可序列化的物件可否設成transient,從而將之排除在複製過程之外。上例程式碼改進如下。
 

class Professor implements Serializable
{
    String name;
    
int age;
    Professor(String name,
int age)
    
{
        
this.name=name;
        
this.age=age;
    }

}

class Student implements Serializable
{
    String name;
//常量物件。
int age;
    Professor p;
//學生1和學生2的引用值都是一樣的。
    Student(String name,int age,Professor p)
    
{
        
this.name=name;
        
this.age=age;
        

相關推薦

JAVA複製複製

JAVA中淺複製與深複製 1.淺複製與深複製概念⑴淺複製(淺克隆)被複制物件的所有變數都含有與原來的物件相同的值,而所有的對其他物件的引用仍然指向原來的物件。換言之,淺複製僅僅複製所考慮的物件,而不復制它所引用的物件。 ⑵深複製(深克隆)被複制物件的所有變數都含有與原來的物件

JavaCloneable介面的複製複製

深拷貝(深複製)和淺拷貝(淺複製)是兩個比較通用的概念,尤其在C++語言中,若不弄懂,則會在delete的時候出問題,但是我們在這幸好用的是Java。雖然java自動管理物件的回收,但對於深拷貝(深複製)和淺拷貝(淺複製),我們還是要給予足夠的重視,因為有時這兩個概念往往會給我們帶來不小的困惑。 淺拷貝是指拷

Javaclone方法以及複製複製

Java中處理基本資料型別(如:int , char , double等),都是採用按值傳遞的方式執行,除此之外的其他型別都是按照引用傳遞(傳遞的是一個物件的引用)的方式執行。物件在函式呼叫時和使用“=”賦值時都是引用傳遞。 Java中clone方法的作用是為了在現實程式

複製複製

淺複製 舉個複製程式碼的例子: function clone(p,s) { var s = s || {}; for (var prop in p) { s[prop] = p[prop]; } return s; } var a = {name: ’Che

初始JAVA拷貝和拷貝

exc 深度復制 tst 圖片 們的 over 地方 per 發生 1. 簡單變量的復制 public static void main(String[] args) { int a = 5; int b = a;

C++ 拷貝建構函式拷貝拷貝

淺拷貝建構函式 看一段拷貝建構函式的程式碼 #include <iostream> #include <cstring> using namespace std; class Array{ public : Array()

python3拷貝拷貝的實現方式、區別

python3淺拷貝與深拷貝的實現方式、區別: list1 = [1,2,3] list2 = list1 list1[0] = 0 print(list2) print(list1) 列印的結果: [0, 2, 3] [0, 2, 3] 小結: 通過把一個列表變數名賦

Java 陣列 拷貝拷貝

http://www.cppblog.com/baby-fly/archive/2010/11/16/133763.html 定義一個數組int[] a={3,1,4,2,5}; int[] b=a;  陣列b只是對陣列a的又一個引用,即淺拷貝。如果改變陣列b中元素的值

深入理解Java克隆克隆

前言 克隆,即複製一個物件,該物件的屬性與被複制的物件一致,如果不使用Object類中的clone方法實現克隆,可以自己new出一個物件,並對相應的屬性進行資料,這樣也能實現克隆的目的。 但當物件屬性較多時,這樣的克隆方式會比較麻煩,所以Object類中實現了clone方法,用於克隆物件。 Java中的

Python複製拷貝拷貝

1.物件的三要素 id、type以及value,id唯一標識一個物件,相當於地址,id一樣,說明就是同一個東西。type和value就是字面意思。 2.==和is ==比較的是value,is比較的是id,意思是  “是否為同一個物件”,條件比==要嚴格。 3.可變物

python列表的複製,扯一下拷貝拷貝的區別

將一個列表的資料複製到另一個列表中。使用列表[:],可以呼叫copy模組 import copy A = [21,22,23,24,['a','b','c','d'],25,26] B = A #直接賦值 C = A[:]

陣列複製拷貝和拷貝

深淺拷貝針對如物件、陣列之類的複雜型別。 就陣列而言。 深拷貝 拷貝的陣列變數和原來的陣列變數是指向兩塊不同的空間,二者的操作互相不影響。 int[] a = new int[]{1,2

Java clone、複製複製複製建構函式

在java中的物件重複利用通常有兩種渠道:複製引用、克隆,不管何種方法,它們都是為了減少物件重複建立和賦值操作,一定程度上提高效率。這裡就有關物件複用的幾種方式和關係進行探討。共識java中的物件分為兩派:值型別和引用型別,這是因為他們的傳遞方式,一個是值傳遞,一個是引用傳遞

java複製複製

開發十年,就只剩下這套架構體系了! >>>   

java克隆克隆

java 深克隆 淺克隆概念:俗話就是拷貝一個副本一般實現:實現Cloneable 接口重寫clone()方法部分代碼public Object clone() { Object o = null; try { o = (Student) super.clone();// O

python拷貝拷貝

post 相同 pre body python and aos deep light 淺拷貝可以拿丈夫與媳婦公用一張銀行卡來舉例 # python >>> husband = [‘liang‘,123,[10000,6000]] #丈夫的銀行卡信息

java List復制:拷貝拷貝

zab row 實例 ets span for deepcopy dex 就是 Java的拷貝可以分為三種:淺拷貝(Shallow Copy)、深拷貝(Deep Copy)、延遲拷貝(Lazy Copy)。 在java中除了基本數據類型之外(int,long,short等)

OpenCV影象的拷貝拷貝 = copy clone區別

下面介紹三種OpenCV複製影象的方法: 方法1、過載運算子= 使用過載運算子“=”進行的拷貝是一種淺拷貝,雖然它們有不同的矩陣頭,但是二者共享相同的記憶體空間,二者內容相互關聯,任何一個變數變化的同時另一個變數也隨之改變。 /*OpenCV v1版本*/ IplImage im

複製複製

Python中,複製有以下幾種方法 1.賦值複製 >>>a = [1, 2, 3] >>>b = a >>>b [1, 2, 3] 此時的複製,b僅僅是指向了a所在的記憶體空間,在記憶體中,並沒有申請一處新的空間來儲存列表b,a和b在

Python賦值、拷貝拷貝的區別

賦值,其實就是物件的引用,對新物件的如何修改都會影響到原始物件。 Python中有兩種拷貝操作:淺拷貝和深拷貝。 copy.copy(x):返回x的淺拷貝。 copy.deepcopy(x):返回x的深拷貝。 那麼都是拷貝,淺拷貝和深拷貝有什麼不同嗎? 淺