日期:2014-05-20  浏览次数:20841 次

深度复制
java中如何实现深度复制

------解决方案--------------------
http://www.cnblogs.com/greatandforever/archive/2008/11/05/1326916.html
------解决方案--------------------
如果成员变量是基本数据类型的话,可以直接赋值
如果成员变量是对象的话,必须要获得该对象的clone
Java code

import java.util.*;

public class MyObject 
{
    private int num;
    private Date date;
    
    public Object clone()
    {
        MyObject object = new MyObject();
        object.num = num;        //基本类型直接赋值
        object.date = (Date) date.clone();    //对象必须要clone
        return object;
    }
}

------解决方案--------------------
自己写的深度克隆的小例子,需要实现Cloneable接口.
克隆时加了个null判断,在其他例子中不经常看到,也不知道是否应该进行判断.随便看看吧

Java code

import java.util.Vector;

/**
 * 深度克隆. 要求实现克隆接口
 */

public class A implements Cloneable {
    // 数组克隆
    public String name[];
    // 对象克隆
    public Vector<B> claB;

    /**
     * 构造方法
     */    
    public A() {
        name = new String[2];
        claB = new Vector<B>();
    }

    /**
     * 重写克隆方法. 深度克隆
     */
    @Override
    public Object clone() {
        A o = null;
        try {
            o = (A) super.clone();
            
            // name对象的克隆
            if(name != null){ // 在一些例子中没有这句null判断,为避免错误,这句是我自己加上的,不知道是否应该.
                o.name = (String[]) name.clone();// 深度clone
            }else{
                o.name = null;
            }
            
            // vector对象的克隆
            o.claB = new Vector<B>();// 将clone进行到底
            if(claB != null){ // 在一些例子中没有这句null判断,为避免错误,这句是我自己加上的,不知道是否应该.
                for (int i = 0; i < claB.size(); i++) {
                    B temp = (B) claB.get(i).clone();// 当然ClassB也要实现相应clone方法
                    o.claB.add(temp);
                }
            }else{
                o.claB = null;
            }
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return o;
    }

    /**
     * 克隆类中包含其他类时,深度克隆时,其他类也要实现克隆接口.
     */
    private class B implements Cloneable {
        private String b1;

        private String b2;

        public String getB1() {
            return b1;
        }

        public void setB1(String b1) {
            this.b1 = b1;
        }

        public String getB2() {
            return b2;
        }

        public void setB2(String b2) {
            this.b2 = b2;
        }
        
        /**
         * 重写克隆方法
         */
        @Override
        public Object clone() {
            A o = null;
            try {
                o = (A) super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return o;
        }
    }
}

------解决方案--------------------
简单的说,对于基本类型来说,只有深拷贝,对于引用类型来说,有浅拷贝和深拷贝两种

浅拷贝,就是用一个变量的值(即变量的内存信息)直接对另一个变量赋值

A a = new A();
A b = a; //浅拷贝,就是把a的值赋给b,也就是说把a的内存信息复制到b的内存
为什么说是浅拷贝,因为这样的话,a和b指向相同的对象,所以改变a的属性会引起b属性的改变,不能达到a和b是互相独立互不影响的效果,所以称这样的拷贝为"浅"拷贝,也就是一种虚假的拷贝,并没能达到b完完全全是a的复制品

深拷贝,就是让变量指向一个新的对象,并用另一个对象的信息初始化新的对象

A a = new A();
...
A b = new A();
b.xxx = a.xxx; //用a.xxx初始化b.xxx属性,如果a.xxx属性不是基本类型,那么也要像b那样重新生成一个xxx对象,让b.xxx指向该对象,并且用a.xxx的信息去初始化新的对象
这样的话,改变a的属性不会影响b属性的改变,也就是说a和b是互不影响的,所以称这样的拷贝为"深"拷贝,b是a的一个完完全全的复制品

------解决方案--------------------
Java code
class A {
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public A dClone() {
        A ret = new A();
        ret.setAge(this.getAge());
        return ret;
    }
}

public class Test8 {

    private int bb;
    private A arg;

    public int getBb() {
        return this.bb;
    }

    public void setBb(int bb) {
        this.bb = bb;
    }

    public A getArg() {
        return this.arg;
    }

    public void setArg(A arg) {
        this.arg = arg;
    }

    public Test8() {
        arg = new A();
        arg.setAge(12);
    }

    public Test8 dClone() {
        Test8 ret = new Test8();
        ret.setBb(this.getBb());
        ret.setArg(this.getArg().dClone());
        return ret ;
    }

    public static void main(String[] args) {
        Test8 b = new Test8();
        System.out.println(b + "-----" + b.getArg());

        Test8 b1 = b.dClone();
        System.out.println(b1 + "-----" + b1.getArg());

        // 两次打印的应该是不一样的

    }

}