两种不同的克隆方法,浅克隆(ShallowClone)和深克隆(DeepClone)。
在Java语言中,数据类型分为值类型(基本数据类型)和引用类型,byte、short、int、long、flout、double、boolean、char8种简单数据类型,引用类型包括类、接口、数组等复杂类型。浅克隆和深克隆的主要区别在于是否支持引用类型的成员变量的复制。
1,浅克隆实验
Student类,含有两个成员变量
package clone; class Student implements Cloneable { private int age;//基本数据类型 private Address address;//引用数据类型 public int getage() { return age; } public void setage(int age) { this.age = age; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } @Override public Object clone() { Student stu = null; try { stu = (Student) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return stu; } } class Address { private String address; public String getaddress() { return address; } public void setaddress(String address) { this.address = address; } }
测试类
package clone; public class Test { public static void main(String args[]) { Student stu1 = new Student(); Address addr = new Address(); 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,深度克隆实验
package clone; class Student1 implements Cloneable{ private int number; private Address1 addr; public Address1 getAddr() { return addr; } public void setAddr(Address1 addr) { this.addr = addr; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } @Override public Object clone() { Student1 stu = null; try{ stu = (Student1)super.clone(); //浅复制 }catch(CloneNotSupportedException e) { e.printStackTrace(); } stu.addr = (Address1)addr.clone(); //深度复制 return stu; } } class Address1 implements Cloneable { private String add; public String getAdd() { return add; } public void setAdd(String add) { this.add = add; } @Override public Object clone() { Address1 addr = null; try{ addr = (Address1)super.clone(); }catch(CloneNotSupportedException e) { e.printStackTrace(); } return addr; } }
package clone; public class Test1 { public static void main(String args[]) { Address1 addr = new Address1(); addr.setAdd("杭州市"); Student1 stu1 = new Student1(); 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