浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
总之深浅克隆都会在堆中新分配一块区域,区别在于对象属性引用的对象是否需要进行克隆(递归性的)。
1、浅克隆
public class Student implements Cloneable{
private String name;
private Integer age;
private Teacher teacher;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", teacher=" + teacher +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Teacher implements Cloneable{
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public static void main(String[] args) throws Exception{
Teacher teacher = new Teacher();
teacher.setName("张老师");
teacher.setAge(42);
Student student = new Student();
student.setName("李晓明");
student.setAge(15);
student.setTeacher(teacher);
System.out.println(student);
Student student2 = (Student) student.clone();
student2.setAge(18);
teacher.setAge(50);
System.out.println(student);
System.out.println(student2);
}
student2克隆student后teacher都指向同一内存地址,修改student的teacher对象,student中teacher也随之改变
2、手动实现深克隆
对象类都需要实现Cloneable接口
public class Student implements Cloneable{
private String name;
private Integer age;
private Teacher teacher;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", teacher=" + teacher +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Student student = (Student) super.clone();
//手动克隆teacher
student.setTeacher((Teacher) student.getTeacher().clone());
return student;
}
}
public class Teacher implements Cloneable{
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public static void main(String[] args) throws Exception{
Teacher teacher = new Teacher();
teacher.setName("张老师");
teacher.setAge(42);
Student student = new Student();
student.setName("李晓明");
student.setAge(15);
student.setTeacher(teacher);
System.out.println(student);
Student student2 = (Student) student.clone();
student2.setAge(18);
teacher.setAge(50);
System.out.println(student);
System.out.println(student2);
}
student2的teacher并不会随之改变
3、序列化实现深克隆
public class Student implements Serializable{
private static final long serialVersionUID = -5763470826096290328L;
private String name;
private Integer age;
private Teacher teacher;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", teacher=" + teacher +
'}';
}
public Object deepCopy()throws Exception
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//将当前这个对象写到一个输出流当中,因为这个对象的类实现了Serializable这个接口,
// 所以在这个类中,有一个引用,这个引用如果实现了序列化,那么这个也会写到这个输出流当中
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
//这个就是将流中的东西读出类,读到一个对象流当中,这样就可以返回这两个对象的东西,实现深克隆
}
}
public class Teacher implements Serializable{
private static final long serialVersionUID = 4018726304594413514L;
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public static void main(String[] args) throws Exception{
Teacher teacher = new Teacher();
teacher.setName("张老师");
teacher.setAge(42);
Student student = new Student();
student.setName("李晓明");
student.setAge(15);
student.setTeacher(teacher);
System.out.println(student);
Student student2 = (Student) student.deepCopy();
student2.setAge(18);
teacher.setAge(50);
System.out.println(student);
System.out.println(student2);
}
执行结果同上面一致