我们知道在Java在java中,传参时,都是以传值的形式进行。对于基本数据类型,传递的是数据的拷贝,对于引用类型,传递的引用的拷贝。为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。至于怎么样来实现Clone我们必须做以下的事情:
1> 在派生类中覆盖基类的clone(),并声明为public。
2> 在派生类的clone()方法中,调用super.clone()。
3> 在派生类中实现Cloneable接口。
4> 没有抽象方法的接口叫标识接口。
5> 为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在运行时刻,Object
的clone()方法能识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原
始对象的内容一一复制到新的对象空间去。
我们看下面的例子:
class TestClone
{
public static void main(String[] args)
{
Animal an1=new Animal("Dog",50);
Animal an2=(Animal)an1.clone();
an2.name="Fox";
an2.weight=30;
System.out.println(an1);
}
}
class Animal implements Cloneable
{
String name;
int weight;
public Animal(String name,int weight)
{
this.name=name;
this.weight=weight;
}
public String toString()
{
return "name="+name+","+"weight="+weight;
}
public Object clone()
{
Object o=null;
try
{
o=super.clone();
}
catch(CloneNotSupportedException e)
{
System.out.println(e.toString());
}
return o;
}
}
运行结果如下:
F:\Java Develop>javac TestClone.java
F:\Java Develop>java TestClone
name=Dog,weight=50
我们看到我们修改an2的值并没有影响到an1里的值,这就是克隆的作用.是因为在这里通过Clone我们在内存中有2块地方用来储存不同的an1,an2
我们在看下面一个例子,我们再增加一个动物的饲养员类,来相关到具体的每个动物.
class TestClone
{
public static void main(String[] args)
{
Feeder f=new Feeder("google",50);
Animal an1=new Animal("Dog",50,f);
Animal an2=(Animal)an1.clone();
an2.f.name="baidu";
an2.f.age=60;
System.out.println(an1.f.name);
System.out.println(an1.f.age);
}
}
/*
class Feeder implements Cloneable
{
String name;
int age;
public Feeder(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 Feeder
{
String name;
int age;
public Feeder(String name,int age)
{
this.name=name;
this.age=age;
}
}
class Animal implements Cloneable
{
String name;
int weight;
Feeder f;
public Animal(String name,int weight,Feeder f)
{
this.name=name;
this.weight=weight;
this.f=f;
}
public String toString()
{
return "name="+name+","+"weight="+weight;
}
public Object clone()
{
Object o=null;
//Animal o=null;
try
{
o=super.clone();
}
catch(CloneNotSupportedException e)
{
System.out.println(e.toString());
}
//o.f=(Feeder)f.clone();
return o;
}
}
我们看输出结果:
F:\Java Develop>javac TestClone.java
F:\Java Develop>java TestClone
baidu
60
从结果可以看出来我们修改了an2.f.name和an.f.age但是an1去发生了变化,这是因为我们没有对Feeder类进行克隆,这就是浅克隆,为了解决这个问题我们需要用到Deeply克隆,java默认的克隆方式是浅克隆.
代码如下:
class TestClone
{
public static void main(String[] args)
{
Feeder f=new Feeder("google",50);
Animal an1=new Animal("Dog",50,f);
Animal an2=(Animal)an1.clone();
an2.f.name="baidu";
an2.f.age=60;
System.out.println(an1.f.name);
System.out.println(an1.f.age);
}
}
class Feeder implements Cloneable
{
String name;
int age;
public Feeder(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 Animal implements Cloneable
{
String name;
int weight;
Feeder f;
public Animal(String name,int weight,Feeder f)
{
this.name=name;
this.weight=weight;
this.f=f;
}
public String toString()
{
return "name="+name+","+"weight="+weight;
}
public Object clone()
{
//Object o=null;
Animal o=null;
try
{
o=(Animal)super.clone();
}
catch(CloneNotSupportedException e)
{
System.out.println(e.toString());
}
o.f=(Feeder)f.clone();
return o;
}
}
输出结果如下:
F:\Java Develop>javac TestClone.java
F:\Java Develop>java TestClone
google
50
java浅克隆是指copy类里所有没有引用类型的变量.Deeply Clone则刚好相反.