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);*/
                
    }

}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值