一、作用
想拷贝一个新对象出来,并且对新对象的修改不会影响到旧对象。
二、概念
1. 浅拷贝
对基本数据类型进行值传递,对引用数据类型进行引用传递,并没有创建新对象。
2. 深拷贝
对基本数据类型进行值传递,对引用数据类型进行引用传递,创建新对象,并复制其内容。
三、使用
1. 普通的
JavaBean 中不包含引用类型数据(String 类型的成员可以有)
public class Student implements Cloneable {
private int id;
private int age;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student() {}
public Student(int id, int age) {
this.id = id;
this.age = age;
}
public Student(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
@NonNull
@Override
public Object clone() {
Student o = null;
try {
o = (Student) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
}
}
@Test
public void clone2() {
Student s = new Student(1, 10, "小明");
Student s2 = (Student) s.clone();
System.out.println("s.hashcode=" + s.hashCode());
System.out.println("s2.hashcode=" + s2.hashCode());
s2.setAge(11);
s2.setName("小红");
System.out.println("s.age=" + s.getAge());
System.out.println("s2.age=" + s2.getAge());
System.out.println("s.name=" + s.getName());
System.out.println("s2.name=" + s2.getName());
}
s.hashcode=458209687
s2.hashcode=233530418
s.age=10
s2.age=11
s.name=小明
s2.name=小红
2. 类中包含引用类型成员变量
给 Student 中增加一引用类型成员
private Farther mFarther;
要想引用类型的实例成员也完成深拷贝,需要完成以下操作:
- Farther 类实现
Cloneable
接口,重写clone()
方法
public class Farther implements Cloneable {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Farther() {}
public Farther(String name) {
this.name = name;
}
@NonNull
@Override
public Object clone() {
Farther o = null;
try {
o = (Farther) super.clone();
return o;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
}
}
- 修改 Student 类的
clone()
方法
@NonNull
@Override
public Object clone() {
Student o = null;
try {
o = (Student) super.clone();
o.setFarther((Farther) mFarther.clone());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
}
测试
@Test
public void clone3() {
Farther f1 = new Farther("小明爸爸");
Student s = new Student(1, 10, "小明", f1);
Student s2 = (Student) s.clone();
System.out.println("s.hashcode=" + s.hashCode());
System.out.println("s2.hashcode=" + s2.hashCode());
s2.setAge(11);
s2.setName("小红");
System.out.println("s.age=" + s.getAge());
System.out.println("s2.age=" + s2.getAge());
System.out.println("s.name=" + s.getName());
System.out.println("s2.name=" + s2.getName());
System.out.println("s.farther.hashCode=" + s.getFarther().hashCode());
System.out.println("s2.farther.hashCode=" + s2.getFarther().hashCode());
}
s.hashcode=458209687
s2.hashcode=233530418
s.farther.hashCode=683287027
s2.farther.hashCode=1766822961
3. List 的深拷贝
List 的深拷贝,就是对其中的每个对象都完成深拷贝。
@Test
public void clone4() {
List < Student > students = new ArrayList < > ();
Farther f1 = new Farther("小明爸爸");
Student s = new Student(1, 10, "小明", f1);
students.add(s);
Farther f2 = new Farther("小红爸爸");
Student s2 = new Student(1, 10, "小红", f2);
students.add(s2);
List < Student > cloneStudents = new ArrayList < > ();
for (int i = 0; i < students.size(); i++) {
Student student = students.get(i);
Student cloneStudent = (Student) student.clone();
cloneStudents.add(cloneStudent);
}
for (int i = 0; i < students.size(); i++) {
System.out.println("old:" + i + ":" + students.get(i).toString());
System.out.println("new:" + i + ":" + cloneStudents.get(i).toString());
}
}
测试结果
old:0:Student{student.hashCode=458209687, name='小明', mFarther,hashCode=233530418}
new:0:Student{student.hashCode=683287027, name='小明', mFarther,hashCode=1766822961}
old:1:Student{student.hashCode=254413710, name='小红', mFarther,hashCode=1496724653}
new:1:Student{student.hashCode=553264065, name='小红', mFarther,hashCode=897697267}