1. 程式人生 > >java 中 的 deep copy 與 shallow copy

java 中 的 deep copy 與 shallow copy

當我們檢視 Object 中的clone() 方法的API時發現有這樣一段話:‘......this method  performs a "shallow copy" of this object, not a "deep copy" operation....’

事實確實這樣,是一個複雜物件該方式是無法實現clone的。 仔細看下會發現該方法 使用‘protected’修飾的,這樣造成的後果就是:對那些簡單地使用一下這個類的客戶程式設計師來說,他們不會預設地擁有這個方法;其次,我們不能利用指向基礎類的一個控制代碼來呼叫clone()(儘管那樣做在某些情況下特別有用,比如用多形性的方式克隆一系列物件)。

那麼我們如何實現深度copy呢?? 

上程式碼前先看看 ObjectOutputStream   的   writeObject(Object obj)  和

                             ObjectInputStream      的    readObject()  方法的API

方法writeObject(Object obj):

   /**
     * Write the specified object to the ObjectOutputStream.  The class of the
     * object, the signature of the class, and the values of the non-transient
     * and non-static fields of the class and all of its supertypes are
     * written.  Default serialization for a class can be overridden using the
     * writeObject and the readObject methods.  Objects referenced by this
     * object are written transitively so that a complete equivalent graph of
     * objects can be reconstructed by an ObjectInputStream.

     *...............................

方法readObject():

      Objects referenced by this object are read  transitively so that a complete equivalent graph of objects is  reconstructed by readObject.

程式碼還是最能說明問題的:

package com.test.clone;

import java.io.Serializable;

public class Person implements Serializable{  

    private static final long serialVersionUID = 1L;
    private int age;  
    private String name;  
      
    public Person(){};  
    public Person(int age,String name){  
        this.age=age;  
        this.name=name;  
    }  
      
    public int getAge() {  
        return age;  
    }  
    public void setAge(int age) {  
        this.age = age;  
    }  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }
    
    @Override
    protected final Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return super.clone();
    }
    
    @Override
    public String toString() {
        return "Person [age=" + age + ", name=" + name + "]";
    }
    
    public static void main(String[] args) {
        Person person = new Person();
        //person.clone();
        
    }
    
    
}

-------------------------------------------------------------------------------------

package com.test.clone;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

public class PersonDeepCopyTest {
    
    public static <T> void printList(List<T> list){  
        System.out.println("---begin---");  
        for(T t : list){  
            System.out.println(t);  
        }  
        System.out.println("---end---");  
    }
    
    public static <T> void printArray(T[] array){  
        System.out.println("---begin---");  
        for(T t : array){  
            System.out.println(t);  
        }  
        System.out.println("---end---");  
    }
    
    /**
     * 深度copylist
     * @param <T>
     * @param src
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static <T> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException {  
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();  
        ObjectOutputStream out = new ObjectOutputStream(byteOut);  
        out.writeObject(src);  
      
        ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());  
        ObjectInputStream in = new ObjectInputStream(byteIn);  
        @SuppressWarnings("unchecked")  
        List<T> dest = (List<T>) in.readObject();  
        return dest;  
    }
    
    /**
     *
     * @param <G>
     * @param src
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static <G> List<G> deep4Copy(List<G> src) throws IOException, ClassNotFoundException{
        ByteArrayOutputStream byteout= new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(byteout);
        out.writeObject(src);
        
        ByteArrayInputStream bytein= new ByteArrayInputStream(byteout.toByteArray());
        ObjectInputStream in = new ObjectInputStream(bytein);
        
        List<G> dest = (List<G>) in.readObject();  
        return dest;  
    }
    
    /**
     * 深度copyMap
     * @param <G>
     * @param <E>
     * @param src
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static <G,E> Map<G,E> deep4MapCopy(Map<G,E> src) throws IOException, ClassNotFoundException{
        ByteArrayOutputStream byteout= new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(byteout);
        out.writeObject(src);
        
        ByteArrayInputStream bytein= new ByteArrayInputStream(byteout.toByteArray());
        ObjectInputStream in = new ObjectInputStream(bytein);
        
        Map<G,E> dest = (Map<G,E>) in.readObject();  
        return dest;  
    }
    
    /**
     * 深度copy Hashtable
     * @param <G>
     * @param <E>
     * @param src
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static <G,E> Hashtable<G,E> deep4HashTableCopy(Hashtable<G,E> src) throws IOException, ClassNotFoundException{
        ByteArrayOutputStream byteout= new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(byteout);
        out.writeObject(src);
        
        ByteArrayInputStream bytein= new ByteArrayInputStream(byteout.toByteArray());
        ObjectInputStream in = new ObjectInputStream(bytein);
        
        Hashtable<G,E> dest = (Hashtable<G,E>) in.readObject();  
        return dest;  
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        List<Person> srcList=new ArrayList<Person>();  
        Person p1=new Person(20,"123");  
        Person p2=new Person(21,"ABC");  
        Person p3=new Person(22,"abc");  
        
        srcList.add(p1);  
        srcList.add(p2);  
        srcList.add(p3);
        
        
/*        List<Person> destList=new ArrayList<Person>(srcList.size());  
        for(Person p : srcList){  
            destList.add(p);  //無法實現深度copy
        }  
                  
        printList(destList);  
        srcList.get(0).setAge(100);  
        printList(destList);
        printList(srcList);*/
        
        
/*        List<Person> destList=new ArrayList<Person>();  
        destList.addAll(srcList); //無法實現深度copy
        printList(destList);  
        srcList.get(0).setAge(100);  
        printList(destList);
        printList(srcList);*/
        
        
        List<Person> destList=deepCopy(srcList);  //可實現List深度copy
        printList(destList);  
        destList.get(0).setAge(100);  
        printList(destList);
        printList(srcList);
        
/*        Map<String,Person> srcMap=new HashMap<String,Person>();  
        Person p1=new Person(20,"123");  
        Person p2=new Person(21,"ABC");  
        Person p3=new Person(22,"abc");  
        srcMap.put(p1.getName(),p1);
        srcMap.put(p2.getName(),p2);  
        srcMap.put(p3.getName(),p3);
        
        Map<String, Person> destMap = deep4MapCopy(srcMap);//可實現Map深度copy
        System.out.println(destMap);
        destMap.get("abc").setAge(100);
        System.out.println(destMap);
        System.out.println(srcMap);*/
        
/*        Hashtable<String,Person> srcHashTable=new Hashtable<String,Person>();  
        Person p1=new Person(20,"123");  
        Person p2=new Person(21,"ABC");  
        Person p3=new Person(22,"abc");  
        srcHashTable.put(p1.getName(),p1);
        srcHashTable.put(p2.getName(),p2);  
        srcHashTable.put(p3.getName(),p3);
        
        Map<String, Person> desthashtable = deep4HashTableCopy(srcHashTable);//可實現List深度copy
        System.out.println(desthashtable);
        desthashtable.get("abc").setAge(100);
        System.out.println(desthashtable);
        System.out.println(srcHashTable);*/
                
    }

}


相關推薦

java deep copy shallow copy

當我們檢視 Object 中的clone() 方法的API時發現有這樣一段話:‘......this method  performs a "shallow copy" of this object, not a "deep copy" operation....’ 事實確

Python的淺複製(shallow copy)和深複製(deep copy)

近期雜事太多,部落格一直沒更新,9月最後一天了,總得寫點吧 今天記一下以前碰到過,最近又碰到的問題:python的深複製和淺複製 神奇的python中,copy竟然還有兩種,一深一淺(emm),來看看它們有什麼區別。 python值管理方式 這本質原因是pyt

deep copy and shallow copy

並不是 hal bject target vps www col att truct 鏈接A:淺拷貝就是成員數據之間的一一賦值:把值賦給一一賦給要拷貝的值。但是可能會有這樣的情況:對象還包含資源,這裏的資源可以值堆資源,或者一個文件。。當值拷貝的時候,兩個對象就有用共同的資

Java 的寫時複製 (Copy on Write, COW)

Background 寫時複製 (Copy on Write, COW) 有時也叫 "隱式共享", 顧名思義, 就是讓所有需要使用資源 R 的使用者共享資源 R 的同一個副本, 當其中的某一個使用者要對資源 R 進行修改操作時, 先複製 R 的一個副本 R' , 再進行修改操作; Problem 在 J

Java 執行CMD命令(copy/ping)

java實現一些cmd命令 最近在專案中需要用到一些cmd命令,於是利用java提供的Runtime.getRuntime().exec(cmd)方法執行,現對使用的一些命令做一下小結。: 執行copy 命令 執行ping命令 執行copy命令

copy copy

三種 發生 nbsp cnblogs 復制 end his code spa 1 import copy 2 names = ["zhangyang", ‘guyun‘, ‘xiangpeng‘, [‘jack‘,‘tom‘], ‘xuliangchen‘] 3 n

Java字節對象之間的轉換

ring str arr cti void too trac port ear 近期公司裏面用到了消息隊列,而正如我們知道的是消息隊列之間的是通過二進制形式的。以下就分享一下java中字節與對象之間的轉換。 主要是用到了ByteArrayOutputStream和Ob

java的類對象

共享 泛化 不能 變量聲明 eas diag 特征 類變量 set 面向對象編程主要有三個特征:封裝、繼承和多態。 封裝 一個簡單的問題 一個能輸出圓的面積的Java應用程序。 public class ComputerCircleArea

javapublic voidpublic static void區別

sta erro ati 對象 方法 這樣的 調用 必須 靜態方法 static 方法可以被main方法直接調用,而非static方法不可以。因為static方法是屬於類的,是類方法。可以通過類名.方法名直接調用。而非static方法必須等對象被new出來以後才能使用,因而

Java重載重寫的區別

ref 類對象 就是 不同 3.4 做出 同方 相同 默認 簡單的個人記憶,重寫是子類中的方法與父類的方法參數、返回值一模一樣,重載是對於同一個類中的方法,方法名相同,參數類型、個數不同。當父類的引用指向子類對象的時候,子類中如果有對於父類方法的重寫,則調用的是子類重寫過的

Java自動裝箱拆箱詳解

sans 做的 sys 實例 代碼 而在 byte 裝箱 bsp 在講裝箱與拆箱之前我們要先了解一下這個問題的來源: Java中的類型分為基本類型(Primitive type)和類類型(Class type)兩種: 基本類型包括byte型、char型、short型

java的equals==

bsp 源碼 內部 brush ++ class object類 功能 length equals()與==都是java中用於進行比較的,返回boolean值,不同的是equals()是Object類中定義的一個方法,==是一個比較運算符。下面是equals()在O

(五)聊一聊深CopyCopy

otto list int print 技術分享 作用 code height 工廠 一、關於淺copy與深copy 首先說明一下: 在python中,賦值其實就是對象的引用,變量就是對象的一個標簽,如果把內存對象比喻成一個個房間,那麽變量就是門牌號。 深copy與淺

java的常量變量學習記錄

進行 變量類型 過程 java OS 變化 邏輯 存儲 nal 常量的定義:程序運行過程中,其值不會發生變化(更準確的說是不可以發生變化)的量叫做常量。 常量的作用:簡單、直觀的描述一個東西,是變量的基礎,是程序運行的基礎。 常量分為兩大類:一類:原始值(不需要定義即可使用

java的裝箱拆箱

net chan import HA com 裝箱 ava art spa java中的裝箱與拆箱 ,參考這三個博客,寫的很好 1 http://www.importnew.com/15712.html 2 https://www.cnblogs.com/dol

JAVA的BigIntegerBigDecimal類功能強大

取余 並且 log 加減乘除 value java 構造函數 () eof BigInteger類是java為了處理大數字二專門制作的類,可以處理很大的數字(理論上無限大),並且可以實現大數字的類似於int所有數學運算。對算法題來說,再也不怕出現超出int範圍的運算了! 同

copycopy舉例

deepcopy clas 分享 src -s 技術 技術分享 png TP 例1: 1 #!/usr/bin/env python 2 import copy 3 d1 = {‘x‘:1,‘y‘:2,‘z‘:[3,4.5]} 4 d2 = d1 5 d3

Java的異常錯誤處理

ror sys lse AC alt xtend tro ima onu 編譯型異常和運行時異常 編譯時異常是指程序正確 而由外界條件不滿足而產生的異常 java 中要求必須去捕捉住這類異常 不然無法通過編譯 運行時異常是指程序存在著bug

JAVA接口抽象類

rac 構造 轉換 希望 就是 pub 成員變量 類型 規則 抽象類總結 抽象類的概念:是使用關鍵字abstract修飾的類就是抽象類; 抽象類的產生:當多個不能相互繼承的類具有相同的功能時,就需要將共同的信息向上抽取,放到公共的父類中;如果公共的父類只能描述所有子類都

copycopy

lib 意義 blog 數據 hat itl 了解 ble copies copy 和 deep copy 是前兩天讓我特別迷惑的兩個 Python 概念。今天下決心花時間搞懂了兩者的區別,更重要的是通過它們認識了 Python 存儲數據的一些有趣特點。 雖然第一次聽說