JAVA 对象克隆clone

来源:互联网 发布:合同档案管理系统软件 编辑:程序博客网 时间:2024/05/18 21:38

      有时候我们希望克隆一个已存在的对象,并对其进行操作,但是不希望改变原对象,这时使用clone技术就非常方便了。但是使用clone,也有一些需要注意的地方,因为clone有浅层克隆和深层克隆。还是习惯先直接上代码,结合代码讲解。

      注:如果你希望某个类具有clone功能,该类必须实现接口Cloneable,它是一个标识接口,告诉JVM,这个类具有clone权利。

      为了方便测试,以下代码写得很随便,没有按照规范些,呵呵。

public class A implements Cloneable{//为了方便测试,以下变量都用public修饰public int num;public String name;public String[] nickNames=new String[2];public B b=new B();public A clone(){A a=null;try{a=(A)super.clone();}catch(CloneNotSupportedException e){e.printStackTrace();}return a;}}
public class B {//为了方便测试,变量用public修饰public String name;}
public class C {public static void main(String[] args){A a1=new A();//给a1的属性设值a1.num=10;a1.name="a1";a1.nickNames[0]="a1-1";a1.nickNames[1]="a1-2";a1.b.name="a1.b";//打印a1System.out.println("a1克隆前:");print(a1);A a2=a1.clone();//给a2属性设值a2.num=20;a2.name="a2";a2.nickNames[0]="a2-1";a2.nickNames[1]="a2-2";a2.b.name="a2.b";//打印a2System.out.println("克隆对象a2:");print(a2);//再打印a1System.out.println("a1克隆后:");print(a1);}public static void print(A a){System.out.println("num="+a.num+"    name="+a.name+"   nickNames[0]="+a.nickNames[0]+"    nickNames[1]="+a.nickNames[1]+"    b.name="+a.b.name);}}

看看运行结果:

a1克隆前:
num=10    name=a1   nickNames[0]=a1-1    nickNames[1]=a1-2    b.name=a1.b
克隆对象a2:
num=20    name=a2   nickNames[0]=a2-1    nickNames[1]=a2-2    b.name=a2.b
a1克隆后:
num=10    name=a1   nickNames[0]=a2-1    nickNames[1]=a2-2    b.name=a2.b

发现a1除了int num,String name的内容没变,其它都变了,这是怎么回事呢?这就是所谓的浅层克隆,也就是克隆不彻底,画张草图表示下.

发现虽然引用对象a1和引用对象a2都指向了各自的实例对象,但是他们的实例对象内部的数组对象和类对象引用(除了String)都指向了同一处。为了解决这问题,就需要深层克隆。

A代码修改如下。

public class A implements Cloneable{//为了方便测试,以下变量都用public修饰public int num;public String name;public String[] nickNames=new String[2];public B b=new B();public A clone(){A a=null;try{a=(A)super.clone();a.nickNames=new String[this.nickNames.length];//重新new一个System.arraycopy(this.nickNames, 0, a.nickNames, 0, this.nickNames.length);//复制a.b=(B)this.b.clone();//B克隆}catch(CloneNotSupportedException e){e.printStackTrace();}return a;}}


由于A中对B进行了克隆,所以B也必须实现接口Cloneable

public class B implements Cloneable{//为了方便测试,变量用public修饰public String name;public B clone(){B b=null;try{b=(B)super.clone();}catch(CloneNotSupportedException e){e.printStackTrace();}return b;}}


测试类C不需修改,再看看运行结果。

a1克隆前:
num=10    name=a1   nickNames[0]=a1-1    nickNames[1]=a1-2    b.name=a1.b
克隆对象a2:
num=20    name=a2   nickNames[0]=a2-1    nickNames[1]=a2-2    b.name=a2.b
a1克隆后:
num=10    name=a1   nickNames[0]=a1-1    nickNames[1]=a1-2    b.name=a1.b

发现a2就算进行了修改也无法影响到a1了,这就是我们要的效果

 

 

原创粉丝点击