clone() 是 Object 方法,通过该方法克隆一个一模一样的对象。一般通过实现 cloneable 接口实现该方法,在 Object 类中该方法是 native 方法,基于底层操作系统实现。
// 具体使用
A a1 = new A();
A a2 = (A)a1.clone();
当我们调用 clone() 方法后,首先根据原对象的大小申请内存空间,申请完内存空间后,将原对象内存域复制到新申请的内存空间,返回引用类型。也就是说,从内存地址来看,clone() 会创建一个全新的对象。
根据结果,克隆分两种:
- 深克隆:引用类型属性也克隆
- 浅克隆:引用类型属性不克隆
对于只包含基础类型的对象,深克隆、浅克隆无影响。对于包含引用类型的对象,浅克隆前后引用类型属性指向同一块内存,也就是说虽然克隆产生一个全新的对象,但它的引用属性还指向被克隆对象引用属性指向的对象。
浅克隆改深克隆也比较简单:引用类型也实现 cloneable() 接口,重写当前类的 clone() 方法,在方法中手动克隆引用类型属性并赋值,举个例子:
class A implements Cloneable { //省略 }
class B implements Cloneable {
private A a;
@Override
protected Object clone() throws CloneNotSupportedException {
B b = (B)super.clone();
b.a = (A)this.a.clone();
return b;
}
}
然而上述例子也不完全是深克隆,假设 A 对象包含 String 引用类型,那么该属性实际上仍是浅克隆,也就是说,只要包含引用类型,就需要无限递归的重写下去,这实际上非常麻烦,而且一旦引用 SDK 里面像 String 这种不能重写的类,根本无法实现。