Java对象拷贝
2019-02-20 本文已影响0人
Charein
常用的对象拷贝有2种方式,分别是
浅拷贝
,深拷贝
。
1. 浅拷贝
在浅拷贝中,如果原型对象的成员变量是值类型,将复制一份给拷贝对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给拷贝对象,也就是说原型对象和拷贝对象的成员变量指向相同的内存地址。
看如下例子
public class ClassRoom implements Cloneable {
public String name;
public int studentNum;
public Student student;
public ClassRoom(String name, int studentNum, Student student) {
this.name = name;
this.studentNum = studentNum;
this.student = student;
}
@Override
public String toString() {
return "ClassRoom{" +
"name='" + name + '\'' +
", studentNum=" + studentNum +
", student=" + student +
'}';
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Student implements Cloneable {
public String name;
public int age;
public boolean isBoy;
public Student(String name, int age, boolean isBoy) {
this.name = name;
this.age = age;
this.isBoy = isBoy;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", isBoy=" + isBoy +
'}';
}
}
拷贝Student对象测试
public static void main(String[] args) {
Student student = new Student("cyy", 20, true);
System.out.println("student: " + student);
Student studentNew;
try {
studentNew = (Student) student.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return;
}
student.name = "yt";
student.age = 10;
student.isBoy = false;
System.out.println("studentNew: " + studentNew);
// 输出
// student: Student{name='cyy', age=20, isBoy=true}
// studentNew: Student{name='cyy', age=20, isBoy=true}
}
从打印结果可以发现student对象里面的name,age,isBoy全部被拷贝到studentNew对象。
如果对象里面又嵌套一个对象的情况
public static void main(String[] args) {
Student student = new Student("cyy", 20, true);
ClassRoom classRoom = new ClassRoom("一年级", 100, student);
System.out.println("classRoom: " + classRoom);
ClassRoom classRoomNew;
try {
classRoomNew = (ClassRoom) classRoom.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return;
}
classRoom.name = "二年级";
classRoom.studentNum = 200;
classRoom.student.age = 10;
classRoom.student.name = "yt";
classRoom.student.isBoy = false;
System.out.println("classRoomNew: " + classRoomNew);
// 输出
// classRoom: ClassRoom{name='一年级', studentNum=100, student=Student{name='cyy', age=20, isBoy=true}}
// classRoomNew: ClassRoom{name='一年级', studentNum=100, student=Student{name='yt', age=10, isBoy=false}}
}
从打印结果可以发现classroom的name,studentNum内容被拷贝classroomNew对象,而student对象没有被拷贝过来(这时就需要使用深拷贝)。
2.深拷贝
在深拷贝中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给拷贝对象,深拷贝将原型对象的所有引用对象也复制一份给拷贝对象。
看如下例子
public class ClassRoom implements Cloneable {
public String name;
public int studentNum;
public Student student;
public ClassRoom(String name, int studentNum, Student student) {
this.name = name;
this.studentNum = studentNum;
this.student = student;
}
@Override
public String toString() {
return "ClassRoom{" +
"name='" + name + '\'' +
", studentNum=" + studentNum +
", student=" + student +
'}';
}
@Override
public Object clone() throws CloneNotSupportedException {
ClassRoom classRoom = (ClassRoom) super.clone();
classRoom.student = (Student) student.clone();
return classRoom;
}
}
public class Student implements Cloneable {
public String name;
public int age;
public boolean isBoy;
public Student(String name, int age, boolean isBoy) {
this.name = name;
this.age = age;
this.isBoy = isBoy;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", isBoy=" + isBoy +
'}';
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public static void main(String[] args) {
Student student = new Student("cyy", 20, true);
ClassRoom classRoom = new ClassRoom("一年级", 100, student);
System.out.println("classRoom: " + classRoom);
ClassRoom classRoomNew;
try {
classRoomNew = (ClassRoom) classRoom.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return;
}
classRoom.name = "二年级";
classRoom.studentNum = 200;
classRoom.student.age = 10;
classRoom.student.name = "yt";
classRoom.student.isBoy = false;
System.out.println("classRoomNew: " + classRoomNew);
// 输出
// classRoom: ClassRoom{name='一年级', studentNum=100, student=Student{name='cyy', age=20, isBoy=true}}
// classRoomNew: ClassRoom{name='一年级', studentNum=100, student=Student{name='cyy', age=20, isBoy=true}}
}
从打印结果可以发现classRoom对象的name,studentNum和student对象内容全部被拷贝到classRoomNew对象。
注:浅拷贝/深拷贝需要实现Cloneable接口,并覆盖clone方法,而且clone方法必须是public访问。