克隆的目的:快速创建一个已有对象的副本。 克隆的步骤:
1. Object的clone()源代码简介
/**
* 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()方法来克隆对象。
2.浅克隆(shadow clone) 克隆就是复制一个对象的复本.若只需要复制对象的字段值(对于基本数据类型,如:int,long,float等,则复制值;对于复合数据类型仅复制该字段值,如数组变量则复制地址,对于对象变量则复制对象的reference。 例子:
public class ShadowClone implements Cloneable{
private int a; // 基本类型
private int[] b; // 非基本类型
// 重写Object.clone()方法,并把protected改为public
@Override
public Object clone(){
ShadowClone sc = null;
try
{
sc = (ShadowClone) super.clone();
} catch (CloneNotSupportedException e){
e.printStackTrace();
}
return sc;
}
public int getA()
{
return a;
}
public void setA(int a)
{
this.a = a;
}
public int[] getB() {
return b;
}
public void setB(int[] b) {
this.b = b;
}
} 然后进行测试:
public class Test{
public static void main(String[] args) throws CloneNotSupportedException{
ShadowClone c1 = new ShadowClone();
//对c1赋值
c1.setA(100) ;
c1.setB(new int[]{1000}) ;
System.out.println('克隆前c1: a=' c1.getA() ' b=' c1.getB()[0]);
//克隆出对象c2,并对c2的属性A,B,C进行修改
ShadowClone c2 = (ShadowClone) c1.clone();
//对c2进行修改
c2.setA(50) ;
int []a = c2.getB() ;
a[0]=5 ;
c2.setB(a);
System.out.println('克隆前c1: a=' c1.getA() ' b=' c1.getB()[0]);
System.out.println('克隆后c2: a=' c2.getA() ' b[0]=' c2.getB()[0]);
}
} 结果为:
克隆前c1: a=100 b=1000 c1和c2的对象模型:
可以看出,基本类型可以使用浅克隆,而对于引用类型,由于引用的是内容相同,所以改变c2实例对象中的属性就会影响到c1。所以引用类型需要使用深克隆。另外,在开发一个不可变类的时候,如果这个不可变类中成员有引用类型,则就需要通过深克隆来达到不可变的目的。 3.深克隆(deep clone) 深克隆与浅克隆的区别在于对复合数据类型的复制。若对象中的某个字段为复合类型,在克隆对象的时候,需要为该字段重新创建一个对象。 例子:
public class DeepClone implements Cloneable {
private int a; // 基本类型
private int[] b; // 非基本类型
// 重写Object.clone()方法,并把protected改为public
@Override
public Object clone(){
DeepClone sc = null;
try
{
sc = (DeepClone) super.clone();
int[] t = sc.getB();
int[] b1 = new int[t.length];
for (int i = 0; i < b1.length; i ) {
b1[i] = t[i];
}
sc.setB(b1);
} catch (CloneNotSupportedException e){
e.printStackTrace();
}
return sc;
}
public int getA()
{
return a;
}
public void setA(int a)
{
this.a = a;
}
public int[] getB() {
return b;
}
public void setB(int[] b) {
this.b = b;
}
}
结果为: 克隆前c1: a=100 b=1000 克隆前c1: a=100 b=1000克隆后c2: a=50 b[0]=5
对象模型:
4、总结:
参考文章:http://blog.csdn.net/mazhimazh/article/details/16828505 |
|
来自: liang1234_ > 《深浅克隆》