问一个对象clone()的问题

philo_xu 2008-01-20 04:55:50
代码如下:


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"吗?
...全文
153 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaowillis 2009-09-20
  • 打赏
  • 举报
回复
对的, 对想的拷贝是拷贝引用, 是对shallow copy 而言的, 问题是你的代码已经实现的是deep copy了. 这就是为什么你的professor 的值拷贝后是不一样的.
dracularking 2008-01-23
  • 打赏
  • 举报
回复
浅克隆只是不复制它所考虑对象中的引用型对象。
grayliu 2008-01-23
  • 打赏
  • 举报
回复
LS的赞,LZ散点吧。。。哈哈,我接点。。。
lanicetomas 2008-01-22
  • 打赏
  • 举报
回复
楼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()放进行对教授的内部数据的拷贝。对于整个拷贝来说就是深层拷贝,而不是简单拷贝引用了。
既然不是拷贝简单的拷贝引用,由于不是指向同一个内存区,那么你改变了数据,并不会影响原来的值。
明白了吗?


kerry_lulu 2008-01-22
  • 打赏
  • 举报
回复
你调用的是object的clone方法,他是逐位复制并创建足够大的内存空间
也就是说其实在堆中又产生了一个原对象的copy,他和源对象已经没有关系了
dracularking 2008-01-20
  • 打赏
  • 举报
回复
clone creates and returns a copy of this object.

就是创建对象拷贝啊

62,623

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧