目录
一、浅克隆
1)什么是浅克隆?
被Clone的对象的所有变量都含有原来对象相同的值,而引用变量还是原来对用的引用【拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象。】即若对象中有引用数据类型的变量则无法拷贝
public class test {
public static void main(String[] args) {
User user1 = new User("zs", new People("zs", 1));
try {
User clone = user1.clone();
clone.setName("ls");
System.out.println(user1.getName().hashCode());//3897
System.out.println(clone.getName().hashCode());//3463
//引用类变量地址并未发生变化
System.out.println(user1.getPeople().hashCode());//1134712904
System.out.println(clone.getPeople().hashCode());//1134712904
System.out.println(user1 == clone); //false
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
class User{
private String name;
private People people;
public User(){}
public User(String name, People people) {
this.name = name;
this.people = people;
}
public People getPeople() {
return people;
}
public void setPeople(People people) {
this.people = people;
}
@Override
protected User clone() throws CloneNotSupportedException {
return (User) super.clone();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class People{
String name;
Integer no;
public People(){}
public People(String name, Integer no) {
this.name = name;
this.no = no;
}
}
二、深克隆
1)什么是深克隆?
被克隆对象的所有变量都含有原来的对象相同的值,引用变量也重新复制了一份【不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象】引用数据类型的变量地址改变。
class test1 {
public static void main(String[] args) {
Clazz clazz1 = new Clazz(1L, "zs", new Student(1L, "zs", 1));
try {
Clazz clone = clazz1.clone();
clone.setName("ls");
System.out.println(clazz1.getName().hashCode());//3897
System.out.println(clone.getName().hashCode());//3463
//引用类变量地址并发生变化
System.out.println(clazz1.getStu().hashCode());//1956725890
System.out.println(clone.getStu().hashCode());//356573597
System.out.println(clazz1 == clone); //false
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
class Student implements Cloneable{
private Long id;
private String name;
private Integer sex;
public Student() {
}
public Student(Long id, String name, Integer sex) {
this.id = id;
this.name = name;
this.sex = sex;
}
@Override
protected Student clone() throws CloneNotSupportedException {
return (Student)super.clone();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", sex=" + sex + "]";
}
}
public class Clazz implements Cloneable {
private Long number;
private String name;
private Student stu;
public Clazz() {
}
public Clazz(Long number, String name, Student stu) {
this.number = number;
this.name = name;
this.stu = stu;
}
@Override
protected Clazz clone() throws CloneNotSupportedException {
Clazz cla = (Clazz)super.clone();
cla.stu = stu.clone(); // 引用对象也需要Clone
return cla;
}
public Long getNumber() {
return number;
}
public void setNumber(Long number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student getStu() {
return stu;
}
public void setStu(Student stu) {
this.stu = stu;
}
@Override
public String toString() {
return "Clazz [number=" + number + ", name=" + name + ", stu=" + stu + "]";
}
}
三、总结
- 浅克隆:只复制基本类型的数据,引用类型的数据只复制了引用的地址,引用的对象并没有复制,在新的对象中修改引用类型的数据会影响原对象中的引用。
- 深克隆:是在引用类型的类中也实现了clone,是clone的嵌套,复制后的对象与原对象之间完全不会影响。
- 使用序列化也能完成深复制的功能:对象序列化后写入流中,此时也就不存在引用什么的概念了,再从流中读取,生成新的对象,新对象和原对象之间也是完全互不影响的。
- 使用clone实现的深克隆其实是浅克隆中嵌套了浅克隆,与toString方法类似