问一个对象clone()的问题代码如下:Java codeclass StringTest {/*** @param args*/public static void cha
问一个对象clone()的问题
代码如下:
Java codeclass 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()放进行对教授的内部数据的拷贝。对于整个拷贝来说就是深层拷贝,而不是简单拷贝引用了。
既然不是拷贝简单的拷贝引用,由于不是指向同一个内存区,那么你改变了数据,并不会影响原来的值。
明白了吗?