概述
JAVA中对象的拷贝分两种:深拷贝和浅拷贝。 对象的拷贝在内存中的体现即是在堆中新开辟一片空间,然后将要拷贝的对象拷贝一份到新开辟的空间上来。要拷贝的对象可能有各种基本数据类型的成员变量,也可能有各种引用型数据类型的成员变量。浅拷贝的做法是只拷贝基本数据类型的变量,不拷贝引用型成员变量,也就是新拷贝对象中的这些引用型成员变量和旧对象指向的对象相同,两者对这些对象的操作相互影响。而深拷贝的做法是两种类型的成员变量都拷贝一份新的,说白了深拷贝就是浅拷贝的递归,直到被被引用对象的成员变量只有基本数据类型的成员变量。 无论是深拷贝还是浅拷贝都是拷贝的一种实现方式,默认使用的是浅拷贝。如果要实现深拷贝需要重写对象的clone方法(继承自Object),实现方式见代码实例。 实现深拷贝的另一种方式是使用对象的序列化。代码示例
public class CloneDemo {
public static void main(String[] args) throws CloneNotSupportedException {
Test t = new Test("t1",new T("t1"));
Test t2 = (Test) t.clone();
t2.field = "t2";
t2.t.field = "t2";
System.out.println(t);
System.out.println(t2);
}
}
class Test implements Cloneable{
String field;
T t;
public Test(String field, T t) {
super();
this.field = field;
this.t = t;
}
@Override
public String toString() {
return "Test [field=" + field + ", t=" + t + "]";
}
@Override
protected Object clone() throws CloneNotSupportedException {
Test o = null;
o = (Test)super.clone();
//o.t = (T)t.clone();
return o;
}
}
class T implements Cloneable{
String field;
public T(String field) {
super();
this.field = field;
}
@Override
public String toString() {
return "T [field=" + field + "]";
}
@Override
protected Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
如果不打开代码中的注释,即使用的是浅拷贝:只对要考的对象及对象所持有的基本数据类型成员变量进行拷贝。 运行结果如下:
Test [field=t1, t=T [field=t2]]
Test [field=t2, t=T [field=t2]]
如果打开了代码中的注释,即使用的是深拷贝:对要拷贝对象及对象所持有的基本数据类型的成员变量进行拷贝及对象所持有的引用型成员变量进行递归拷贝。被打开注释的那句话就是手动递归拷贝的。 运行结果如下:Test [field=t1, t=T [field=t1]]
Test [field=t2, t=T [field=t2]]
---------------=====Caution=====--------------------
另外在JAVA中,并不是你的代码支持了深拷贝就会在任何时候拷贝都使用深拷贝,由于深拷贝需要花费更多的性能消耗,在JAVA中以下情况强制使用浅拷贝:
数组的clone()方法;
Arrays.copyOf()方法;
部分集合框架类(内部数据结构是数组的类)的clone方法,因为其clone方法的内部使用的是Arrays.copyOf()方法