纸上得来终觉浅,绝知此事要躬行
--陆游 问渠那得清如许,为有源头活水来 --朱熹
clone和Copy:当有一个对象Person p1=new Person("name",age);Person p2=p1;此时只是简单的copy了一下引用,p1和p2都指向了内存中的同一个对象,修改p1和p2中任何一个都会影响到对方。当函数的参数是对象时,传递的是引用类型,在对象函数内部的操作会影响到外边对象。如果希望传递的是对象的一个拷贝时,这时就需要用到object的clone()方法。)拷贝对象返回的是一个新对象,而不是引用;拷贝对象与new操作符返回的新对象的区别就是这个拷贝对象已经包含了原来对象的一些信息,而不是对象的初始信息。什么时候使用shallow Clone(浅拷贝,影子拷贝),什么时候使用deep Clone(深拷贝):主要看具体域对象的性质是什么,如果是基本类型使用shallow Clone,如果是reference variable(引用变量)使用deep Clone。
实现克隆的步骤:
(1)实现Cloneable接口,Cloneable没有任何抽象方法,称为标志接口。
(2)覆盖基类 的clone方法,并声明为public
(3)在派生类中重写clone方法,并调用super.clone()
在clone中分为浅拷贝和深拷贝,浅拷贝就是不管参数是基本类型还是引用类型,直接调用super.clone()进行拷贝,结果引用类型还是指向相同的内存;深拷贝就是在调用super.clone()之后,还要调用引用参数的clone()函数,进行拷贝,来达到深拷贝。
浅拷贝:
(1) 基本的数据类型(String)是会拷贝复制一份新的对象
(2)引用对象还是引用同一份对象。
浅拷贝示例代码:
public class Info { public int idnumber; public int getIdnumber() { return idnumber; } public void setIdnumber(int idnumber) { this.idnumber = idnumber; } } public class Person implements Cloneable{ private int age; private String nameString; public Info info; public Info getInfo() { return info; } public void setInfo(Info info) { this.info = info; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getNameString() { return nameString; } public void setNameString(String nameString) { this.nameString = nameString; } public String toString() { return "name:"+nameString+",age:"+age+",idnumber"+info.idnumber; } public Object clone() { Person person=null; try { person=(Person)super.clone(); //浅拷贝 //person.info=(Info)info.clone(); } catch (CloneNotSupportedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } return person; } } public class Hello { public static void main(String[] args) { // TODO 自动生成的方法存根 Info info=new Info(); info.setIdnumber(100); Person person1=new Person(); person1.setAge(10); person1.setNameString("tiantian"); person1.info=info; Person person2=(Person)person1.clone(); person2.setNameString("hello"); person2.setAge(20); person2.info.setIdnumber(200); System.out.println("person2"+person2); System.out.println("person1"+person1); } }
最后的结果是:
person2name:hello,age:20,idnumber200 person1name:tiantian,age:10,idnumber200
person1和person2的基本类型name和age都改变了,但引用类型的idnumber数值没变。
深拷贝:
(1)对存在的引用类型也进行拷贝,浅拷贝与深拷贝的代码还是有不同点的。
深拷贝代码示例:
public class Info implements Cloneable {//Info也进行拷贝 public int idnumber; public int getIdnumber() { return idnumber; } public void setIdnumber(int idnumber) { this.idnumber = idnumber; } public Object clone() { Info info=null; try { info=(Info)super.clone(); } catch (CloneNotSupportedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } return info; } } public class Person implements Cloneable{ private int age; private String nameString; public Info info; public Info getInfo() { return info; } public void setInfo(Info info) { this.info = info; } public Person() { // TODO 自动生成的构造函数存根 } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getNameString() { return nameString; } public void setNameString(String nameString) { this.nameString = nameString; } public String toString() { return "name:"+nameString+",age:"+age+",idnumber"+info.idnumber; } public Object clone() { Person person=null; try { person=(Person)super.clone(); //浅拷贝 person.info=(Info)info.clone();//加上这一句就变成了深拷贝,对对象引用也进行一次拷贝 } catch (CloneNotSupportedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } return person; } }
结果:
person2name:hello,age:20,idnumber200 person1name:tiantian,age:10,idnumber100
所有的值都进行了改变。
以上是Java-clone代码示例总结的详细内容。更多信息请关注PHP中文网其他相关文章!