图文并茂的阐述clone方法 && 了解深浅拷贝的概念
clone代表克隆的意思,也就是说把一只绵羊复制粘贴一份,生成一个新的绵羊。
可以看出两只绵羊外形都是一样的,DNA是一样的。
在JAVA中也是如此,如果你希望得到一份对象的拷贝副本,那么就用克隆方法吧。
当你希望制造某个类的克隆时,先让这个类继承继承Cloneable接口
之后要复写clone方法。参照下面代码
package com.umbrella.common.test; public class Person implements Cloneable{ String name; String age; @Override public Person clone() throws CloneNotSupportedException { return (Person)super.clone(); } public void setName(String name){ this.name = name; } public void setAge(String age) { this.age = age; } public String getAge() { return age; } public String getName() { return name; } public void print(){ System.out.println(this.name + "----" + this.age); } }
浅拷贝与深拷贝
深克隆与浅克隆的区别在于对复合数据类型的复制。若对象中的某个字段为复合类型,在克隆对象的时候,需要为该字段重新创建一个对象。
==============浅拷贝=============
package com.umbrella.common.test; public class maintest { public static void main(String[] args) { try{ Person p = new Person(); p.setName("ljh"); p.setAge("10"); Person p1 = p.clone(); p1.setName("ljh"); p1.setAge("11"); Person p2 = p.clone(); p.print(); p1.print(); p2.print();
System.out.println(p.getName()==p1.getName()); System.out.println(p.getAge()==p1.getAge()); System.out.println(p.getAge()==p2.getAge()); System.out.println(p==p2)}catch(Exception e){ e.printStackTrace(); } }}
执行结果:
ljh----10
ljh----11
ljh----10
true
false
true
false
用一副图来说明这个结果:
==============深拷贝=============
如果希望实现深拷贝,那么拷贝的不仅仅是Person对象了,而是对象内的每一个引用的对象也要拷贝
package com.umbrella.common.test; public class Person implements Cloneable{ String name; String age; @Override public Person clone() throws CloneNotSupportedException { Person newPersoon = (Person)super.clone(); return newPersoon; } //------------------------修改一下------直接New一个String-------------------------------- public void setName(String name){ this.name = new String(name) ; } public void setAge(String age) { this.age = new String(age); } public String getAge() { return age; } public String getName() { return name; } public void print(){ System.out.println(this.name + "----" + this.age); } }
运行结果:
ljh----10
ljh----11----
false
false
false
false
可以看出
这样做到了 深度拷贝。。。其实!这里有些牵强,因为String对象是通过New出来的新对象,并不是通过Clone方法实现的,暂且称之为“伪深拷贝”吧,如果希望实现真正深拷贝,可以在类中建立一个内部类,例如
首先注释掉内部类的clone调用,之后放开注释掉的部分,如下文代码所示
package com.umbrella.common.test; public class Person implements Cloneable{ Eat eat ; public Person(){ this.eat = new Eat(); } @Override public Person clone() throws CloneNotSupportedException { Person newPersoon = (Person)super.clone(); // newPersoon.eat = this.eat.clone(); <----------注释掉的clone调用 return newPersoon; } public class Eat implements Cloneable{ @Override public Eat clone() throws CloneNotSupportedException { Eat eat = (Eat)super.clone(); return eat; } } }
之后执行如下main方法:
package com.umbrella.common.test; public class maintest { public static void main(String[] args) { try{ Person p = new Person(); Person p1 = p.clone(); System.out.println(p==p1); System.out.println(p.eat==p1.eat); }catch(Exception e){ e.printStackTrace(); } } }
注释掉Clone输出结果:false true
去掉注释掉Clone输出结果:false false
因为它做到了 彻底的独立!!!