java 对象的克隆(浅克隆和深克隆)
java对象的克隆
一、对象的浅克隆
(1)需要克隆类需要重写Object类的clone方法,并且实现Cloneable接口(标识接口,无需实现任何方法)
(2)当需要克隆的对象中维护着另外一个引用对象,浅克隆不会克隆另外一个引用对下,而是直接复制维护的另外一个引用对象的地址。
(3)对象的浅克隆也不会调用到构造方法。
以下为对象的浅克隆的一个例子:
packagecom.clone; importjava.io.Serializable; /** *Description: *实现了Cloneable接口,并重写Object类的clone方法。 * *@authorlee **/ publicclassCloneDemo1implementsCloneable,Serializable{ //该克隆类封装的信息 publicintid; publicStringname; publicAddressaddress; /** *Desciption: *默认构造器 * **/ publicCloneDemo1(){} /** *Description: *初始化id,name的构造器 * *@paramidid *@paramname名字 *@paramaddress地址 **/ publicCloneDemo1(intid,Stringname,Addressaddress){ this.id=id; this.name=name; this.address=address; } /** *Descriptin: *重写Object类的clone方法。 *iftheobject'sclassdoesnotsupporttheCloneableinterface. *Subclassesthatoverridetheclonemethodcanalsothrowthisexception *toindicatethataninstancecannotbecloned. * *@throwsCloneNotSupportedException **/ @Override publicObjectclone()throwsCloneNotSupportedException{ returnsuper.clone(); } /** *Description: *重写toString方法 * *@return"id="+id+",name="+name **/ @Override publicStringtoString(){ return"id="+id+",name="+name+",address:"+address.getAddress(); } /** *Description: *主方法 * **/ publicstaticvoidmain(String[]args)throwsCloneNotSupportedException{ CloneDemo1c1=newCloneDemo1(1,"c1",newAddress("北京")); //c2复制了c1的地址,并没有复制整个c1对象 CloneDemo1c2=c1; //c3对象的浅克隆,复制了整个对象 CloneDemo1c3=(CloneDemo1)c1.clone(); //当对象c1改变其name或者id的时候,c2也会自动改变。 //因为c2只是复制了c1的地址,并非复制了c1的整个对象。 //相应的c3则不会随着c1改变而改变,意味着c3将c1整个对象克隆一份出来。 //当是,对象的浅克隆不会克隆被克隆对象当中的引用对象。 //因此c1改变其中的Address的引用对象时,c2,c3也会跟着改变。 c1.setName("cc"); c1.address.setAddress("上海"); System.out.println(c1+"\n"+c2+"\n"+c3); } publicintgetId(){ returnid; } publicvoidsetId(intid){ this.id=id; } publicStringgetName(){ returnname; } publicvoidsetName(Stringname){ this.name=name; } } /** *Description: *一个封装着地址的类 * *@authorlee **/ classAddressimplementsSerializable{ publicStringaddress; /** *Description: *默认构造器 * **/ publicAddress(){} /** *Description: *初试化address * *@paramaddress地址 **/ publicAddress(Stringaddress){ this.address=address; } //address的set和get方法 publicStringgetAddress(){ returnaddress; } publicvoidsetAddress(Stringaddress){ this.address=address; } }
二、对象的深克隆
就是利用对象的输入输出流把对象写到文件上,再读取对象的信息,这就是对象的深克隆。
由于对象的浅克隆不会克隆被克隆对象其中的引用对象,而是直接复制其地址。因此,要克隆被克隆对象当中的引用类型则需要对象的深克隆。
而对象的深克隆使用的的对象序列化输入输出。
代码如下:
packagecom.clone; importjava.io.FileInputStream; importjava.io.FileOutputStream; importjava.io.IOException; importjava.io.ObjectInputStream; importjava.io.ObjectOutputStream; /** *Description: *实现对象的深克隆 * *@authorlee **/ publicclassCloneDemo2{ /** *Description: *将对象输出到一个文件当中。 * *@paramc需要被写到文件当中的对象。 **/ publicstaticvoidwriteObject(CloneDemo1c){ ObjectOutputStreamout=null; try{ //将对象输出在一个object.txt文件当中 out=newObjectOutputStream(newFileOutputStream("./object.txt")); out.writeObject(c); }catch(IOExceptione){ System.out.println("写入对象的时候发生了错误。"); e.printStackTrace(); }finally{ //关闭资源 try{ out.close(); }catch(IOExceptione){ e.printStackTrace(); } } } /** *Description: *从文件中读取出一个对象来,并返回。 * *@returnc返回一个对象。 **/ publicstaticCloneDemo1readObject(){ CloneDemo1c=null; ObjectInputStreaminput=null; try{ //从object.txt文件中读取一个对象出来 input=newObjectInputStream(newFileInputStream("./object.txt")); c=(CloneDemo1)input.readObject(); }catch(IOException|ClassNotFoundExceptione){ e.printStackTrace(); System.out.println("读取对象的时候发生了错误。"); }finally{ //关闭资源 try{ input.close(); }catch(IOExceptione){ e.printStackTrace(); } } returnc; } /** *Description: *主方法 * *@throwsCloneNotSupportedException **/ publicstaticvoidmain(String[]args)throwsCloneNotSupportedException{ CloneDemo1c1=newCloneDemo1(1,"c1",newAddress("北京")); //c2对象的浅克隆 CloneDemo1c2=(CloneDemo1)c1.clone(); //c3对象的深克隆 writeObject(c1); CloneDemo1c3=readObject(); //因为对象的深克隆同时也克隆了被克隆对象维护的另外一个对象 //所以,当c1改变其当中的维护的另外一个对象的时候,c3不会随之改变。 //而c2位浅克隆,其维护的另外一个对象只是复制了c1维护的对象的地址,因此会随着c1的改变而改变。 c1.address.setAddress("上海"); System.out.println(c1+"\n"+c2+"\n"+c3); } }
对象的序列化,是需要实现Serializable接口的。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!