谈谈你对java中的深克隆和浅克隆的理解
回答:
(说明:本文针对深克隆和浅克隆的区别和实现方式?这一问题)
talk is cheap#
最近不止一次遇见深浅克隆(深复制,浅复制)的问题,除了印象中有个clone方法外一脸懵逼!!!克隆(复制)在java中是一种常见的操作,目的是快速获取一个对象副本。克隆分为深克隆和浅克隆。
浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
总之深浅克隆都会在堆中新分配一块区域,区别在于对象属性引用的对象是否需要进行克隆(递归性的)。
show you my picture#
pos:当前对象的地址;
son:son属性所指向的地址;
name:对象的name属性。
(相关推荐:java入门教程)
show you my code#
case1:
public class son implements serializable , cloneable{ private string name; private son son; public son() { super(); } public string getname() { return name; } public void setname(string name) { this.name = name; } public son getson() { return son; } public void setson(son son) { this.son = son; } @override public string tostring() { return super.tostring(); } @override protected object clone() throws clonenotsupportedexception { return super.clone(); }}
测试
public static void main(string[] args) throws exception{ // 创建父亲(liliu),儿子(liwu),孙子(liliu)并关联 son father = new son(); father.setname("lisi"); son son = new son(); son.setname("liwu"); son grandson = new son(); grandson.setname("liliu"); father.setson(son); son.setson(grandson); // 调用clone方法 son fathercopy = (son) father.clone(); boolean flag1 = fathercopy==father; boolean flag2 = fathercopy.getson() == son; boolean flag3 = fathercopy.getson().getson() == grandson; // 比较克隆后的地址 system.out.println(flag1);// false system.out.println(flag2);// true system.out.println(flag3);// true // 比较name flag1= fathercopy.getname()==father.getname(); flag2 = fathercopy.getson().getname() == son.getname(); flag3 = fathercopy.getson().getson().getname() == grandson.getname(); system.out.println(flag1);// true system.out.println(flag2);// true system.out.println(flag3);// true //将对象写到流里 bytearrayoutputstream byteout=new bytearrayoutputstream(); objectoutputstream objout=new objectoutputstream(byteout); objout.writeobject(father); //从流里读出来 bytearrayinputstream bytein=new bytearrayinputstream(byteout.tobytearray()); objectinputstream objinput=new objectinputstream(bytein); fathercopy = (son) objinput.readobject(); flag1= fathercopy==father; flag2 = fathercopy.getson() == son; flag3 = fathercopy.getson().getson() == grandson; system.out.println(flag1);// false system.out.println(flag2);// false system.out.println(flag3);// false // 比较name flag1= fathercopy.getname()==father.getname(); flag2 = fathercopy.getson().getname() == son.getname(); flag3 = fathercopy.getson().getson().getname() == grandson.getname(); system.out.println(flag1);// false system.out.println(flag2);// false system.out.println(flag3);// false}
从上文代码及运行结果不难看出,如果对象实现cloneable并重写clone方法不进行任何操作时,调用clone是进行的浅克隆。而使用对象流将对象写入流然后再读出是进行的深克隆。
思考:既然实现cloneable接口并重写clone接口只能进行浅克隆。但是如果类的引用类型属性(以及属性的引用类型属性)都进行浅克隆,直到没有引用类型属性或者引用类型属性为null时,整体上就形成了深克隆。既对象的引用类型属性和属性的应用类型属性都实现coloneable,重写clone方法并在clone方法中进行调用。
protected object clone() throws clonenotsupportedexception { son result = (son) super.clone(); if (son != null) { result.son = (son) son.clone(); } return result;}
个人认为,在选择深克隆方法时,应根据对象的复杂程度,如引用类型属性是否有多层引用类型属性关系。如果对象只有一层或者两层引用类型的属性,选择思考中所提到的方法较为方便,反之则使用对象流。
更多相关面试题请访问:java面试题及答案
以上就是谈谈你对java中的深克隆和浅克隆的理解的详细内容。