Clone
发布日期:2021-09-25 11:48:14 浏览次数:3 分类:技术文章

本文共 4825 字,大约阅读时间需要 16 分钟。

 
java的克隆
/**  * Creates and returns a copy of this {@code Object}. The default  * implementation returns a so-called "shallow" copy: It creates a new  * instance of the same class and then copies the field values (including  * object references) from this instance to the new instance. A "deep" copy,  * in contrast, would also recursively clone nested objects. A subclass that  * needs to implement this kind of cloning should call {@code super.clone()}  * to create the new instance and then create deep copies of the nested,  * mutable objects.  *  * @return a copy of this object.  * @throws CloneNotSupportedException  *             if this object's class does not implement the {@code  *             Cloneable} interface.  */  protected Object clone() throws CloneNotSupportedException {      if (!(this instanceof Cloneable)) {          throw new CloneNotSupportedException("Class doesn't implement Cloneable");      }        return internalClone((Cloneable) this);  }    /*  * Native helper method for cloning.  */  private native Object internalClone(Cloneable o);

clone方法首先会判断对象是否实现了Cloneable接口,若无则抛出CloneNotSupportedException,最后调用internalClone.intervalClone是一个native方法,一般来说native方法的执行效率高于非native方法。

当某个类要复写clone方法时,要实现Cloneable接口,通常的克隆对象都是通过super.clone()来实现。

例子:首先建立一个Student类

package CloneTest;public class Student implements Cloneable{	private String name;	private int age;	private Professor professor;	public String getName() {		return name;	}	public void setName(String name) {		this.name = name;	}	public int getAge() {		return age;	}	public void setAge(int age) {		this.age = age;	}	public Professor getProfessor() {		return professor;	}	public void setProfessor(Professor professor) {		this.professor = professor;	}		public String toString(){		return "Student [name="+name+", age="+age+",professor="+professor+"]";	}		public Object clone() throws CloneNotSupportedException{		return super.clone();	}	}

再建立Professor类

package CloneTest;public class Professor {	private String name;	private int age;	public String getName() {		return name;	}	public void setName(String name) {		this.name = name;	}	public int getAge() {		return age;	}	public void setAge(int age) {		this.age = age;	}		public String toString(){		return "Professor [name=" +name+ ",age=" +age+ "]";	}}
package CloneTest;public class ShadowCopy {	public static void main(String[] args) {		// TODO Auto-generated method stub		Professor p1=new Professor();		p1.setName("Professor Zhang");		p1.setAge(30);				Student s1=new Student();		s1.setName("zhang san");		s1.setAge(20);		s1.setProfessor(p1);				System.out.println(s1);		try{			Student s2=(Student)s1.clone();			Professor p2=s2.getProfessor();			p2.setName("Professor Li");			p2.setAge(45);			s2.setProfessor(p2);			System.out.println("复制后的 s1= "+s1);			System.out.println("复制后的 s2= "+s2);		}catch(Exception e){			e.printStackTrace();		}	}}

通过将s1进行clone给s2,并将s2的professor进行修改,结果如下

Student [name=zhang san, age=20,professor=Professor [name=Professor Zhang,age=30]]复制后的 s1= Student [name=zhang san, age=20,professor=Professor [name=Professor Li,age=45]]复制后的 s2= Student [name=zhang san, age=20,professor=Professor [name=Professor Li,age=45]]

发现,s1和s2的professor信息都进行了修改

将测试代码ShadowCopy进行修改,对复制后S2的name和age也进行修改,即

package CloneTest;public class ShadowCopy {	public static void main(String[] args) {		// TODO Auto-generated method stub		Professor p1=new Professor();		p1.setName("Professor Zhang");		p1.setAge(30);				Student s1=new Student();		s1.setName("zhang san");		s1.setAge(20);		s1.setProfessor(p1);				System.out.println(s1);		try{			Student s2=(Student)s1.clone();						s2.setName("li si");			s2.setAge(18);						Professor p2=s2.getProfessor();			p2.setName("Professor Li");			p2.setAge(45);			s2.setProfessor(p2);			System.out.println("复制后的 s1= "+s1);			System.out.println("复制后的 s2= "+s2);		}catch(Exception e){			e.printStackTrace();		}	}}
Student [name=zhang san, age=20,professor=Professor [name=Professor Zhang,age=30]]复制后的 s1= Student [name=zhang san, age=20,professor=Professor [name=Professor Li,age=45]]复制后的 s2= Student [name=li si, age=18,professor=Professor [name=Professor Li,age=45]]

so,Student的字段如果不是一个引用时,修改clone得到对象的该字段(name,age)并不会影响原来的对象,但是当字段为一个引用时,修改clone得到对象的该字段(professor)时会影响原来的对象。这即浅复制。

so,要进行深复制,首先让Professor实现Cloneable接口,并复写Student类中的clone方法,如下:

public Object clone() throws CloneNotSupportedException{		Student newStudent=new Student();		newStudent.professor=(Professor)professor.clone();		return newStudent;	}
Student [name=zhang san, age=20,professor=Professor [name=Professor Zhang,age=30]]复制后的 s1= Student [name=zhang san, age=20,professor=Professor [name=Professor Zhang,age=30]]复制后的 s2= Student [name=li si, age=18,professor=Professor [name=Professor Li,age=45]]

由此可见,修改clone()得到的s2的任何字段都不会影响s1的字段,这就是深复制的作用。

参考:https://www.cnblogs.com/acode/p/6306887.html

转载地址:https://blog.csdn.net/Autumn03/article/details/80789302 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:原型模式
下一篇:论文-科研

发表评论

最新留言

表示我来过!
[***.240.166.169]2024年04月13日 02时07分27秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章