有的时候我们为了获取对象的一份copy,可以利用Object类的clone方法来实现,要想实现克隆,我们必须在派生类中实现Cloneable interface并覆盖基类的clone()方法,并扩大访问权限为public,在派生类的clone()方法,调用super.clone()。
demo:
class StringTest
{
public static void main(String[] args)
{
Professior p = new Professior("wangwu",50);
Student s1 = new Student("zhangsan",18,p);
Student s2 = (Student)s1.clone();
s2.p.name = "lisi";
s2.p.age = 20;
System.out.println("s1.p.name="+s1.p.name+","+"s1.p.age="+s1.p.age);
}
}
class Student implements Cloneable
{
Professior p;
String name;
int age;
public Student(String name,int age,Professior p)
{
this.name =name;
this.age = age;
this.p = p;
}
public Object clone()
{
Object o = null;
try
{
o=super.clone();
}
catch(CloneNotSupportedException e)
{
System.out.println(e.toString());
}
return o;
}
public String toString()
{
return "name="+name+","+"age="+age;
}
}
class Professior
{
String name;
int age;
public Professior(String name,int age)
{
this.name = name;
this.age = age;
}
}
Result:
D:\jcode>java StringTest
s1.p.name=lisi,s1.p.age=20
通过结果看得出一个问题,当我们修改s2的Professior后,s1对象的Professior对象的值被修改了。不是有clone了2份copy吗?那怎么修改S1的值却影响了S2的值了,那是因为我们克隆的时候只是把Professior的引用复制了一份,而并没有实际在内存中给它分配到一块内存,所以我们clone的时候,其实是把同一个值给复制了2次,所以s1和s2操作的professior都是同一个对象,所以修改S1,必然就影响了S2的professior的值,那我们的本意并非如此,有没有办法解决呢?答案是肯定的。其实我们刚才所做的操作是一个浅克隆,当我们克隆的对象是引用类型的时候,可以用深克隆来实现。就如下面的Demo.
class CloneTest
{
public static void main(String[] args)
{
Boss boss = new Boss("antsoul",25);
Leader leader = new Leader("linda",30);
Employee ep1 = new Employee("zhangsan",107,leader,boss);
Employee ep2 = (Employee)ep1.clone();
ep2.boss.name = "gll";
ep2.boss.age = 60;
System.out.println("ep1.leader.name="+ep1.boss.name);
System.out.println("ep1.leader.age="+ep1.boss.age);
}
}
class Employee implements Cloneable
{
String name;
int eid;
Leader leader;
Boss boss;
Employee(String name,int eid,Leader leader,Boss boss)
{
this.name = name;
this.eid = eid;
this.leader = leader;
this.boss = boss;
}
public Object clone()
{
Employee o = null;
try
{
o = (Employee)super.clone();
}
catch(CloneNotSupportedException e)
{
System.out.println(e.toString());
}
o.leader = (Leader)leader.clone();
o.boss = (Boss)boss.clone();
return o;
}
}
class Leader implements Cloneable
{
String name;
int age;
Leader(String name,int age)
{
this.name = name;
this.age = age;
}
public Object clone()
{
Object o = null;
try
{
o = super.clone();
}
catch(CloneNotSupportedException e)
{
System.out.println(e.toString());
}
return o;
}
}
class Boss implements Cloneable
{
String name;
int age;
Boss(String name,int age)
{
this.name = name;
this.age = age;
}
public Object clone()
{
Object o = null;
try
{
o = super.clone();
}
catch(CloneNotSupportedException e)
{
System.out.println(e.getMessage());
}
return o;
}
}
这里有个疑问了,为什么我们要在派生类中over writte Object的clone()方法时,一定要调用super.clone()呢?
原因是: 在运行时刻,Object中的clone()识别出你要clone的是哪一个对象,然后为此对象分配内存空间,并进行对象的复制,将原始对象的内容一一复制到新的对象空间中去。