java 对象的克隆(浅克隆和深克隆)
程序员文章站
2022-07-19 19:26:40
java 对象的克隆
一、对象的浅克隆
(1)需要克隆类需要重写object类的clone方法,并且实现cloneable接口(标识接口,无需实现任何方法)
(2)...
java 对象的克隆
一、对象的浅克隆
(1)需要克隆类需要重写object类的clone方法,并且实现cloneable接口(标识接口,无需实现任何方法)
(2)当需要克隆的对象中维护着另外一个引用对象,浅克隆不会克隆另外一个引用对下,而是直接复制维护的另外一个引用对象的地址。
(3)对象的浅克隆也不会调用到构造方法。
以下为对象的浅克隆的一个例子:
package com.clone; import java.io.serializable; /** * description: * 实现了cloneable接口,并重写object类的clone方法。 * * @author lee * */ public class clonedemo1 implements cloneable,serializable{ //该克隆类封装的信息 public int id; public string name; public address address; /** * desciption: * 默认构造器 * * */ public clonedemo1(){} /** * description: * 初始化id,name的构造器 * * @param id id * @param name 名字 * @param address 地址 * */ public clonedemo1(int id, string name, address address){ this.id=id; this.name=name; this.address = address; } /** * descriptin: * 重写object类的clone方法。 * if the object's class does not support the cloneable interface. * subclasses that override the clone method can also throw this exception * to indicate that an instance cannot be cloned. * * @throws clonenotsupportedexception * */ @override public object clone() throws clonenotsupportedexception{ return super.clone(); } /** * description: * 重写tostring方法 * * @return "id="+id+", name="+name * */ @override public string tostring(){ return "id="+id+", name="+name+", address:"+address.getaddress(); } /** * description: * 主方法 * * */ public static void main(string[] args) throws clonenotsupportedexception{ clonedemo1 c1 = new clonedemo1(1,"c1",new address("北京")); //c2 复制了c1的地址,并没有复制整个c1对象 clonedemo1 c2 = c1; //c3 对象的浅克隆,复制了整个对象 clonedemo1 c3 = (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); } public int getid() { return id; } public void setid(int id) { this.id = id; } public string getname() { return name; } public void setname(string name) { this.name = name; } } /** * description: * 一个封装着地址的类 * * @author lee * */ class address implements serializable{ public string address; /** * description: * 默认构造器 * * */ public address(){} /** * description: * 初试化address * * @param address 地址 * */ public address(string address){ this.address = address; } //address的set和get方法 public string getaddress() { return address; } public void setaddress(string address) { this.address = address; } }
二、对象的深克隆
就是利用对象的输入输出流把对象写到文件上,再读取对象的信息,这就是对象的深克隆。
由于对象的浅克隆不会克隆被克隆对象其中的引用对象,而是直接复制其地址。因此,要克隆被克隆对象当中的引用类型则需要对象的深克隆。
而对象的深克隆使用的的对象序列化输入输出。
代码如下:
package com.clone; import java.io.fileinputstream; import java.io.fileoutputstream; import java.io.ioexception; import java.io.objectinputstream; import java.io.objectoutputstream; /** * description: * 实现对象的深克隆 * * @author lee * */ public class clonedemo2 { /** * description: * 将对象输出到一个文件当中。 * * @param c 需要被写到文件当中的对象。 * */ public static void writeobject(clonedemo1 c){ objectoutputstream out = null; try{ //将对象输出在一个object.txt文件当中 out = new objectoutputstream(new fileoutputstream("./object.txt")); out.writeobject(c); }catch(ioexception e){ system.out.println("写入对象的时候发生了错误。"); e.printstacktrace(); }finally{ //关闭资源 try{ out.close(); }catch(ioexception e){ e.printstacktrace(); } } } /** * description: * 从文件中读取出一个对象来,并返回。 * * @return c 返回一个对象。 * */ public static clonedemo1 readobject(){ clonedemo1 c = null; objectinputstream input = null; try{ //从object.txt文件中读取一个对象出来 input = new objectinputstream(new fileinputstream("./object.txt")); c = (clonedemo1)input.readobject(); }catch(ioexception | classnotfoundexception e){ e.printstacktrace(); system.out.println("读取对象的时候发生了错误。"); }finally{ //关闭资源 try{ input.close(); }catch(ioexception e){ e.printstacktrace(); } } return c; } /** * description: * 主方法 * * @throws clonenotsupportedexception * */ public static void main(string[] args) throws clonenotsupportedexception { clonedemo1 c1 = new clonedemo1(1,"c1",new address("北京")); //c2 对象的浅克隆 clonedemo1 c2 = (clonedemo1)c1.clone(); //c3对象的深克隆 writeobject(c1); clonedemo1 c3 = readobject(); //因为对象的深克隆同时也克隆了被克隆对象维护的另外一个对象 //所以,当c1改变其当中的维护的另外一个对象的时候,c3不会随之改变。 //而c2位浅克隆,其维护的另外一个对象只是复制了c1维护的对象的地址,因此会随着c1的改变而改变。 c1.address.setaddress("上海"); system.out.println(c1+"\n"+c2+"\n"+c3); } }
对象的序列化,是需要实现serializable接口的。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!