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接口的。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!