Archive for the ‘clone’ tag
java中对象的克隆
java中对象默认为浅拷贝,要深拷贝时需要重载clone方法。在重载时一般要先调用super.clone().这个super.clone()指的是Object类里面定义的clone方法。它根据实际对象的大小来分配空间,并且把内存里面的内容复制过去。如果是基本类型则直接复制,对象类型则只是复制一个引用。
Object类的clone方法是一个native的方法。它先检查当前对象是不是已经实现了Cloneable的接口,如果没有,抛出一个异常;如果已经实现了这个接口,则产生这个对象的类的一个新的实例,并且用这个对象的内容去初始化那个新的实例。源代码里的注释如是说。
* The method clone for class Object performs a
* specific cloning operation. First, if the class of this object does
* not implement the interface Cloneable, then a
* <tt>CloneNotSupportedException is thrown. Note that all arrays
* are considered to implement the interface Cloneable.
* Otherwise, this method creates a new instance of the class of this
* object and initializes all its fields with exactly the contents of
* the corresponding fields of this object, as if by assignment; the
* contents of the fields are not themselves cloned. Thus, this method
* performs a “shallow copy” of this object, not a “deep copy” operation.
public class Main {
public static void main(String[] args) {
B1 b1 = new B1();
b1.a = 11;
b1.b = 22;
b1.c = 33;
b1.d = 44;
b1.e = 55;
B1 b2 = (B1) b1.clone();
System.out.println(b2.a);
System.out.println(b2.b);
System.out.println(b2.c);
System.out.println(b2.d);
System.out.println(b2.e);
}
}
class B1 extends A1 {
public int d = 4;
public int e = 5;
public Object clone() {
System.out.println("B1's clone() is called");
B1 b1;
b1 = (B1) super.clone();
return b1;
}
}
class A1 implements Cloneable{
public int a = 0;
public int b = 1;
public int c = 2;
protected Object clone(){
System.out.println("A1's clone() is called");
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
}
上述代码的执行路径为:13 – 29 – 34 – 46 – 49 ->Object.clone() ->…..
输出:
B1’s clone() is called
A1’s clone() is called
11
22
33
44
55
Cloneable是一个Marker Interface,它里面是空的,仅仅用来让Object.clone()检查一个对象是否可以被克隆。
上述例子中,29行和46行的clone()调用都不会有问题,与Cloneable无关。仅到了49行后才有影响。
A1或者B2当中至少有一个实现了Cloneable接口,否则会抛异常。
但是必须记住,除Object类以外,clone()仅仅是一个普通的方法而已。他们不会去检查是否实现Cloneable(当然良好的习惯要求我们多谢一句instanceof^^)
如果代码改成这样:
public class clone {
public static void main(String[] args) {
B1 b1 = new B1();
b1.a = 11;
b1.b = 22;
b1.c = 33;
b1.d = 44;
b1.e = 55;
B1 b2 = (B1) b1.clone();
System.out.println(b2.a);
System.out.println(b2.b);
System.out.println(b2.c);
System.out.println(b2.d);
System.out.println(b2.e);
}
}
class B1 extends A1 {
public int d = 4;
public int e = 5;
public Object clone() {
System.out.println("B1's clone() is called");
B1 b1;
b1 = (B1) super.clone();
return b1;
}
}
class A1{
public int a = 0;
public int b = 1;
public int c = 2;
protected Object clone(){
System.out.println("A1's clone() is called");
return new B1();
}
}
输出就会变成:
B1’s clone() is called
A1’s clone() is called
0
1
2
4
5
虽然A1和B1都不是Cloneable的,但不会报错。