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秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
spring boot整合thymeleaf,支持JSP和HTML页面开发
2019-04-26
【Java网络编程与IO流】Spring boot整合SSE实现服务器实时推送流信息
2019-04-26
【Leetcode刷题篇】leetcode141 环形链表II
2019-04-26
【Leetcode刷题篇】leetcode160 相交链表
2019-04-26
【Leetcode刷题篇】leetcode169 多数元素
2019-04-26
【Leetcode刷题篇】leetcode461 汉明距离
2019-04-26
【Leetcode刷题篇】leetcode204 计数质数
2019-04-26
【Leetcode刷题篇】leetcode70 爬楼梯
2019-04-26
【Leetcode刷题篇】leetcode739 每日温度
2019-04-26
【Leetcode刷题篇】leetcode121买卖股票的最佳时机
2019-04-26
【面试篇】Java多线程并发-Java关键字volatile详解
2019-04-26
【面试篇】Java的代理模式-静态代理和动态代理详解
2019-04-26
【面试篇】 Java对象拷贝(对象克隆 对象复制)
2019-04-26
【Leetcode刷题篇】leetcode64 最小路径和
2019-04-26
【Leetcode刷题篇】leetcode79 单词搜索
2019-04-26
【Leetcode刷题篇】leetcode300 最长上升子序列
2019-04-26
【Leetcode刷题篇】leetcode394 字符串解码
2019-04-26
【Leetcode刷题篇】leetcode152 乘积最大数组
2019-04-26
【Leetcode刷题篇】leetcode56 合并区间
2019-04-26