Java克隆Clone
☆
什么是Clone
Clone就是得到一个对象x的副本,而且x.clone()
!=
x。Clone分为两种:浅度克隆Shallow Clone和浅度克隆Deep Clone
Object类有clone()方法: protected native Object clone() throws CloneNotSupportedException; 但是Object本身没有implements Cloneable,在执行clone方法时,先检查this.getClass()是否实现了cloneable接口,如果没有实现Cloneable接口,clone()就会抛CloneNotSupportedException返回。否则就会创建一个新的this.getClass()的对象other,并将this每一个field的值赋值给other的对应field,然后返回other。
接口Cloneable起一个标志作用(和Serializable类似),用来标志该类具有克隆功能。
☆ 实现Shallow clone
Shallow Clone只是将基本类型赋值过去,对于对象传的是引用。(String对于比较特别,[一般内容一样则引用一样,轻量级模式])
Shallow Clone
public class Test {
public static void main(String[] args) throws Exception{
Area area=new Area("fujian");
System.out.println("area:"+area);
Area areaClone=area.clone();
System.out.println("areaClone:"+areaClone);
System.out.println("area==areaClone:"+(area==areaClone));
System.out.println("area.getClass()==areaClone.getClass():"+(area.getClass()==areaClone.getClass()));
area.province="jiangxi";
System.out.println("area:"+area);
System.out.println("areaClone:"+areaClone);
}
}
class Area implements Cloneable{
String province;
Area(String province){
this.province=province;
}
@Override
public Area clone(){
Area area=null;
try{
area=(Area)super.clone();
}catch(CloneNotSupportedException cnse){
cnse.printStackTrace();
}
return area;
}
@Override
public String toString(){
return "\tprovince="+province;
}
}
public class Test {
public static void main(String[] args) throws Exception{
Area area=new Area("fujian");
System.out.println("area:"+area);
Area areaClone=area.clone();
System.out.println("areaClone:"+areaClone);
System.out.println("area==areaClone:"+(area==areaClone));
System.out.println("area.getClass()==areaClone.getClass():"+(area.getClass()==areaClone.getClass()));
area.province="jiangxi";
System.out.println("area:"+area);
System.out.println("areaClone:"+areaClone);
}
}
class Area implements Cloneable{
String province;
Area(String province){
this.province=province;
}
@Override
public Area clone(){
Area area=null;
try{
area=(Area)super.clone();
}catch(CloneNotSupportedException cnse){
cnse.printStackTrace();
}
return area;
}
@Override
public String toString(){
return "\tprovince="+province;
}
}
输出结果
area: province=fujian
areaClone: province=fujian
area==areaClone:false
area.getClass()==areaClone.getClass():true
area: province=jiangxi
areaClone: province=fujian
area: province=fujian
areaClone: province=fujian
area==areaClone:false
area.getClass()==areaClone.getClass():true
area: province=jiangxi
areaClone: province=fujian
☆ Shallow Clone的问题
因为对于对象只是拷贝引用,所有就会造成this对其中对象的修改引起other中相应对象的修改,例子如下:
Shallow Clone问题
public class Test {
public static void main(String[] args) throws Exception{
Area area=new Area("fujian","fujian info");
Area areaClone=area.clone();
System.out.println("area:"+area);
System.out.println("areaClone:"+areaClone);
area.province="jiangxi";
area.info.name="new info";
System.out.println("--------After Change-------");
System.out.println("area:"+area);
System.out.println("areaClone:"+areaClone);
}
}
class Area implements Cloneable{
String province;
Info info;
Area(String province,String infoName){
this.province=province;
info=new Info(infoName);
}
@Override
public Area clone(){
Area area=null;
try{
area=(Area)super.clone();
}catch(CloneNotSupportedException cnse){
cnse.printStackTrace();
}
return area;
}
@Override
public String toString(){
return "\tprovince="+province+"\t info="+info.name;
}
}
class Info{
String name;
Info(String name){
this.name=name;
}
}
public class Test {
public static void main(String[] args) throws Exception{
Area area=new Area("fujian","fujian info");
Area areaClone=area.clone();
System.out.println("area:"+area);
System.out.println("areaClone:"+areaClone);
area.province="jiangxi";
area.info.name="new info";
System.out.println("--------After Change-------");
System.out.println("area:"+area);
System.out.println("areaClone:"+areaClone);
}
}
class Area implements Cloneable{
String province;
Info info;
Area(String province,String infoName){
this.province=province;
info=new Info(infoName);
}
@Override
public Area clone(){
Area area=null;
try{
area=(Area)super.clone();
}catch(CloneNotSupportedException cnse){
cnse.printStackTrace();
}
return area;
}
@Override
public String toString(){
return "\tprovince="+province+"\t info="+info.name;
}
}
class Info{
String name;
Info(String name){
this.name=name;
}
}
输出结果
area: province=fujian info=fujian info
areaClone: province=fujian info=fujian info
--------After Change-------
area: province=jiangxi info=new info
areaClone: province=fujian info=new info
area: province=fujian info=fujian info
areaClone: province=fujian info=fujian info
--------After Change-------
area: province=jiangxi info=new info
areaClone: province=fujian info=new info
☆ Deep Clone
有些时候我们不希望this与other之间的修改相互影响,这时就应该用深度克隆。对所有涉及到的对象也实现Clone。
Deep Clone
public class Test {
public static void main(String[] args) throws Exception{
Area area=new Area("fujian","fujian info");
Area areaClone=area.clone();
System.out.println("area:"+area);
System.out.println("areaClone:"+areaClone);
area.province="jiangxi";
area.info.name="new info";
System.out.println("--------After Change-------");
System.out.println("area:"+area);
System.out.println("areaClone:"+areaClone);
}
}
class Area implements Cloneable{
String province;
Info info;
Area(String province,String infoName){
this.province=province;
info=new Info(infoName);
}
@Override
public Area clone(){
Area area=null;
try{
area=(Area)super.clone();
area.info=this.info.clone();
}catch(CloneNotSupportedException cnse){
cnse.printStackTrace();
}
return area;
}
@Override
public String toString(){
return "\tprovince="+province+"\t info="+info.name;
}
}
class Info implements Cloneable{
String name;
Info(String name){
this.name=name;
}
@Override
public Info clone(){
Info info=null;
try{
info=(Info)super.clone();
}catch(CloneNotSupportedException cnse){
cnse.printStackTrace();
}
return info;
}
}
public class Test {
public static void main(String[] args) throws Exception{
Area area=new Area("fujian","fujian info");
Area areaClone=area.clone();
System.out.println("area:"+area);
System.out.println("areaClone:"+areaClone);
area.province="jiangxi";
area.info.name="new info";
System.out.println("--------After Change-------");
System.out.println("area:"+area);
System.out.println("areaClone:"+areaClone);
}
}
class Area implements Cloneable{
String province;
Info info;
Area(String province,String infoName){
this.province=province;
info=new Info(infoName);
}
@Override
public Area clone(){
Area area=null;
try{
area=(Area)super.clone();
area.info=this.info.clone();
}catch(CloneNotSupportedException cnse){
cnse.printStackTrace();
}
return area;
}
@Override
public String toString(){
return "\tprovince="+province+"\t info="+info.name;
}
}
class Info implements Cloneable{
String name;
Info(String name){
this.name=name;
}
@Override
public Info clone(){
Info info=null;
try{
info=(Info)super.clone();
}catch(CloneNotSupportedException cnse){
cnse.printStackTrace();
}
return info;
}
}
输出结果
area: province=fujian info=fujian info
areaClone: province=fujian info=fujian info
--------After Change-------
area: province=jiangxi info=new info
areaClone: province=fujian info=fujian info
area: province=fujian info=fujian info
areaClone: province=fujian info=fujian info
--------After Change-------
area: province=jiangxi info=new info
areaClone: province=fujian info=fujian info
☆ 参考:
http://www.blogjava.net/orangelizq/archive/2007/10/17/153573.html
http://www.blogjava.net/junky/archive/2007/05/08/115928.html