在java中我们时常会遇到需要对对象进行clone的情况,主要是因为Java的别名效应 如下:
SimpleObject a = new SimpleObject();
SimpleObject b = a;
这个时候对b进行修改,a也会被改变.这个时候我们就需要对对象进行clone.
单个对象的clone很简单,实现cloneable接口并继承object 的clone方法就行了
package com.yecg.java.clone;
public class SimpleObject implements Cloneable{
private String property;
public SimpleObject(String property) {
super();
this.property = property;
}
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
public String toString(){
return "simple object property is -----"+property;
}
public Object clone(){
Object a =null;
try {
a =super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return a;
}
}
测试下:
package com.yecg.java.clone;
import java.util.ArrayList;
public class CloneTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//------simple clone
SimpleObject a = new SimpleObject("ini");
SimpleObject b = (SimpleObject)a.clone();
b.setProperty("clo");
System.out.println(a);
System.out.println(b);
}
}
结果:simple object property is -----ini
simple object property is -----clo 说明clone生效.
需要说明的是.虽然在object中有clone方法,但是是protect的,也就是只有在子类中能用,使用a.clone()这种调用方式是不可能实现的.这是因为java要限制clone,并不是每个对象都有clone能力的,如果你想要这个对象拥有clone能力必须要继承这个方法并把它申明为public的.
复杂对象的clone
这种方式的的clone只能说是浅度clone.为什么说是浅度clone呢,如果这个对象中还包含其他对象的引用的话,是无法把这个引用的对象也clone了的
举个例子:
package com.yecg.java.clone;
public class ComplexObject implements Cloneable {
private String property;
private SimpleObject simpleObject;
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
public SimpleObject getSimpleObject() {
return simpleObject;
}
public void setSimpleObject(SimpleObject simpleObject) {
this.simpleObject = simpleObject;
}
public Object clone(){
Object a =null;
try {
a =super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return a;
}
public String toString(){
return "ComplexObject property is ---"+property +" simpleObject property is ---"+simpleObject.getProperty();
}
}
这里一个复杂的对象ComplexObject包含了一个简单对象SimpleObject的引用 ,clone的方法仍然和前面一样
测试下:
package com.yecg.java.clone;
import java.util.ArrayList;
public class CloneTest {
/**
* @param args
*/
public static void main(String[] args) {
//complex clone
SimpleObject simple = new SimpleObject("ini");
ComplexObject complex = new ComplexObject();
complex.setProperty("complex_ini");
complex.setSimpleObject(simple);
ComplexObject complexClone =(ComplexObject)complex.clone();
complexClone.setProperty("complex_clo");
complexClone.getSimpleObject().setProperty("clo");
System.out.println(complex);
System.out.println(complexClone);
}
}
ComplexObject property is ---complex_ini simpleObject property is ---clo
ComplexObject property is ---complex_clo simpleObject property is ---clo
可以看到属性property是确实被clone了,但属性simpleObject没有,对clone后的simpleObject做了改变
complexClone.getSimpleObject().setProperty("clo");
会影响到clone之前对象的值. 这就是浅度复制.只复制对象的表层.
那怎么进行深度复制呢,只需要改下clone方法:public Object clone(){
ComplexObject a =null;
try {
a =(ComplexObject)super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
a.simpleObject =(SimpleObject)a.simpleObject.clone();
return a;
}
在clone自己的同时,也把自己的对象属性进行clone.这就要求你的对象属性必须也要是可以clone的才可以.
集合的clone:
ArrayList里有clone方法,但和复杂对象的clone一样都是浅度clone.怎么深度clone呢
ArrayList<SimpleObject> objectListClo = (ArrayList<SimpleObject>)objectList.clone();
for(int i=0;i<objectListClo.size();i++){
objectListClo.set(i, (SimpleObject)objectListClo.get(i).clone());
}
clone了objectListClo后必须遍历objectListClo里面的每个对象,逐一clone.