两种不同的克隆方法,浅克隆(ShallowClone)和深克隆(DeepClone)。
在Java语言中,数据类型分为值类型(基本数据类型)和引用类型,byte、short、int、long、flout、double、boolean、char8种简单数据类型,引用类型包括类、接口、数组等复杂类型。浅克隆和深克隆的主要区别在于是否支持引用类型的成员变量的复制。
1,浅克隆实验
Student类,含有两个成员变量
packageclone;class Student implementsCloneable {private int age;//基本数据类型
private Address address;//引用数据类型
public intgetage() {returnage;
}public void setage(intage) {this.age =age;
}publicAddress getAddress() {returnaddress;
}public voidsetAddress(Address address) {this.address =address;
}
@OverridepublicObject clone() {
Student stu= null;try{
stu= (Student) super.clone();
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}returnstu;
}
}classAddress {privateString address;publicString getaddress() {returnaddress;
}public voidsetaddress(String address) {this.address =address;
}
}
测试类
packageclone;public classTest {public static voidmain(String args[]) {
Student stu1= newStudent();
Address addr= newAddress();
addr.setaddress("杭州市");
stu1.setage(23);
stu1.setAddress(addr);//把stu1对象克隆得到stu2
Student stu2 =(Student) stu1.clone();
System.out.println("学生1:" + stu1.getage() + ",地址:" +stu1.getAddress().getaddress());
System.out.println("学生2(克隆):" + stu2.getage() + ",地址:" +stu2.getAddress().getaddress());//修改stu2的基本数据类型的成员变量和引用数据类型的成员变量
stu2.setage(25);
addr.setaddress("北京市");
System.out.println("学生1:" + stu1.getage() + ",地址:" +stu1.getAddress().getaddress());
System.out.println("学生2(克隆):" + stu2.getage() + ",地址:" +stu2.getAddress().getaddress());
System.out.println(stu1== stu2); //false
}
}
测试结果:
说明:
1)学生2作为学生1的克隆对象,两个成员比变量的值一致
2)当把学生2的成员变量改掉,发现学生1的基本数据类型没变,但是引用数据类型变了,说明学生2复制的只是学生1的引用数据类型成员变量的引用。
3)学生1和学生2不是同一个对象
浅复制只是复制了addr变量的引用,并没有真正的开辟另一块空间,将值复制后再将引用返回给新对象。
所以,为了达到真正的复制对象,而不是纯粹引用复制。我们需要将Address类可复制化,并且修改clone方法。
2,深度克隆实验
packageclone;class Student1 implementsCloneable{private intnumber;privateAddress1 addr;publicAddress1 getAddr() {returnaddr;
}public voidsetAddr(Address1 addr) {this.addr =addr;
}public intgetNumber() {returnnumber;
}public void setNumber(intnumber) {this.number =number;
}
@OverridepublicObject clone() {
Student1 stu= null;try{
stu= (Student1)super.clone(); //浅复制
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}
stu.addr= (Address1)addr.clone(); //深度复制
returnstu;
}
}class Address1 implementsCloneable {privateString add;publicString getAdd() {returnadd;
}public voidsetAdd(String add) {this.add =add;
}
@OverridepublicObject clone() {
Address1 addr= null;try{
addr= (Address1)super.clone();
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}returnaddr;
}
}
packageclone;public classTest1 {public static voidmain(String args[]) {
Address1 addr= newAddress1();
addr.setAdd("杭州市");
Student1 stu1= newStudent1();
stu1.setNumber(23);
stu1.setAddr(addr);
Student1 stu2=(Student1)stu1.clone();
System.out.println("学生1:" + stu1.getNumber() + ",地址:" +stu1.getAddr().getAdd());
System.out.println("学生2:" + stu2.getNumber() + ",地址:" +stu2.getAddr().getAdd());
stu1.setNumber(25);
addr.setAdd("北京市");
System.out.println("学生1:" + stu1.getNumber() + ",地址:" +stu1.getAddr().getAdd());
System.out.println("学生2:" + stu2.getNumber() + ",地址:" +stu2.getAddr().getAdd());
}
}
这所谓的深度克隆(拷贝)
就是把引用数据类型的变量,这个类再进行克隆,一直克隆到基本数据类型?
如果封装了好多层,就得把每层的类都去实现Cloneable接口,重写clone()方法。
3,利用序列化实现深度克隆
https://www.cnblogs.com/Qian123/p/5710533.html