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

问一个对象clone()的问题
代码如下:

Java code

class StringTest 
{    

    /**
     * @param args
     */
    public static void change(int x,int y)
    {

        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.print("name = "+s1.p.name+",age = "+s1.p.age);
     }

}
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 ce)
        {
            System.out.println(ce.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 ce)
        {
            System.out.println(ce.toString());
        }
        o.p = (Professor)p.clone();
        return o;
        
    }
}




不是说对一个引用类型的对象进行clone()
实际上拷贝的是对象的引用吗?
就是说在栈内存中拷贝了一个引用,实际上两个引用是指向同一个堆内存空间里的对象的。

那为什么这段代码对对象进行clone()后会在堆内存空间了产生了一个对象拷贝呢?
在这个代码里就是s2.p.name = "lisi"没有改变s1.p.name = "wangwu"呢?
不是应该s2.p.name = "lisi"之后,s1.p.name 也应该变成"lisi"吗?

------解决方案--------------------
你调用的是object的clone方法,他是逐位复制并创建足够大的内存空间
也就是说其实在堆中又产生了一个原对象的copy,他和源对象已经没有关系了
------解决方案--------------------
楼Z,我是来要分的,写的让你明白,你就给分,不明白的话,也得给点哦,毕竟我很真诚的回答你的问题!:)

关键:o.p = (Professor)p.clone();

LZ,你首先要了解深层拷贝和浅层拷贝,
浅层拷贝只是简单的拷贝值(包过你说到的引用--地址值),比如,你拷贝的教授对象的时候,它只拷贝了教授对象的内存地址。
深层拷贝,则完完全全的拷贝,比如,你拷贝的教授对象的时候,它拷贝了一整个教授对象。
你的代码将告诉你为什么,
当你Student s2 = (Student)s1.clone();
的时候,调用了Student.clone()方法,然后在方法中调用o = (Student)super.clone();实现了age,name的拷贝,这个是浅层拷贝,把age,name的值给拷贝了,这个能明白吗?
好,继续执行代码,o.p = (Professor)p.clone();关键就是这句了,它会调用(o.p = (Professor)p.clone();)
Professor.clone()方法,这个方法它又把Professor对象的age,name,拷贝下来,把拷贝下来的值保存在Student.p这个对象中,这个也是浅层拷贝,然后return o;,也就是返回拷贝了Student对象的age,namge和Professor对象的age,和name后的对象。明白吗?假如没有o.p = (Professor)p.clone();那么你就没有拷贝Professor对象里面的的数据(age和name),
而只通过o = (Student)super.clone();拷贝了Student的数据,也就是只拷贝了Student.p这个数据(引用值),如果你 s2.p.name = "lisi";s2.p.age = 30;将影响到原来的值,因为你拷贝的是引用值,指向同一个内存区。

上面并没有讲到深层拷贝,其实对于你的整个代码中和整一个拷贝的过程,已经是一个深曾拷贝了,当你拷贝了一个学生对象的时候,学生对象里面又有一个教授对象,然后,你在教授中又写了clone()方法,并且通过调用Student.clone()的过程中,再调用教授的clone()放进行对教授的内部数据的拷贝。对于整个拷贝来说就是深层拷贝,而不是简单拷贝引用了。
既然不是拷贝简单的拷贝引用,由于不是指向同一个内存区,那么你改变了数据,并不会影响原来的值。
明白了吗?