深拷贝和浅拷贝当对象只是基本类型时没有区别。如果复制的对象中含有引用类型,浅拷贝复制的引用类型对象会指向原来的对象,这样修改浅拷贝过后的对象就会影响原来的对象。而深拷贝会给引用对象新建一个新的对象进行clone,两个对象互不影响。
- 第一种方式:实现Cloneable接口,重写clone方法的时候对引用类型变量要进行单独的clone。
- 第二种方式:实现Serializable接口,通过流对象进行写入。
package 深拷贝与浅拷贝;
import java.io.*;
public class DeepCopy {
public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
//1.通过实现cloneable接口来实现深拷贝,即在把基本类型clone后将引用对象类型还要再单独clone一次
Student s1 = new Student(10, "zhangsan", new School(9, "九中"));
Student s2 = s1.clone();
System.out.println(s1);
System.out.println(s2);
//如果school不重写clone方法,则s2获取到的school对象和s1是指向的同一个
s2.getSchool().setGrade(111);
System.out.println(s1);
System.out.println(s2);
//2.序列化方式实现深拷贝
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(s1);
oos.close();
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
Student student = (Student) ois.readObject();
ois.close();
System.out.println(student);
}
}
class Student implements Cloneable, Serializable {
private static final long serialVersionUID = 2631590509760908280L;
private int age;
private String name;
private School school;
public Student(int age, String name, School school) {
this.age = age;
this.name = name;
this.school = school;
}
public School getSchool() {
return school;
}
public void setSchool(School school) {
this.school = school;
}
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;
}
@Override
protected Student clone() throws CloneNotSupportedException {
Student clone = (Student) super.clone();
//这里实现深拷贝,将引用类型对象进行clone
clone.school = school.clone();
return clone;
}
}
class School implements Cloneable,Serializable{
private static final long serialVersionUID = 2631590509760908289L;
private int grade;
private String schoolName;
public School(int grade, String schoolName) {
this.grade = grade;
this.schoolName = schoolName;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
public String getSchoolName() {
return schoolName;
}
public void setSchoolName(String schoolName) {
this.schoolName = schoolName;
}
@Override
protected School clone() throws CloneNotSupportedException {
return (School)super.clone();
}
}