浅拷贝,深拷贝

时间:2021-10-15 21:57:49

浅拷贝

浅拷贝结果是:新对像中包含的引用对象和原对象中包含的引用对象是同一个东东, 改变其中任何一个所包含的引用对象, 另一个也会受到影响

深拷贝

深拷贝结果是:新对象与原对象是完全独立的, 改变其中任何一个所包含的引用对像, 另一个都不会受到影响

 

浅拷贝例子  Object中的clone默认是浅拷贝

1 实现cloneable接口,这是个标记接口

2 重写Object的clone方法,调用父类的clone方法

public class Student {
    private String name; // 姓名
    private int age; // 年龄
    private StringBuffer sex; // 性别

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public StringBuffer getSex() {
        return sex;
    }

    public void setSex(StringBuffer sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", sex=" + sex + "]";
    }
}
public class School implements Cloneable {
    private String schoolName; // 学校名称
    private int stuNums; // 学校人数
    private Student stu; // 一个学生

    public String getSchoolName() {
        return schoolName;
    }

    public void setSchoolName(String schoolName) {
        this.schoolName = schoolName;
    }

    public int getStuNums() {
        return stuNums;
    }

    public void setStuNums(int stuNums) {
        this.stuNums = stuNums;
    }

    public Student getStu() {
        return stu;
    }

    public void setStu(Student stu) {
        this.stu = stu;
    }

    
    
    @Override
    protected School clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return (School)  super.clone();
    }

    
    @Override
    public String toString() {
        return "School [schoolName=" + schoolName + ", stuNums=" + stuNums + ", stu=" + stu + "]";
    }
    
    
    public static void main(String[] args) throws CloneNotSupportedException {
        School s1 = new School();
        s1.setSchoolName("实验小学");
        s1.setStuNums(100);
        Student stu1 = new Student();
        stu1.setAge(20);
        stu1.setName("zhangsan");
        stu1.setSex(new StringBuffer(""));
        s1.setStu(stu1);
        System.out.println(    "s1: " + s1 + " s1的hashcode:" + s1.hashCode() + "  s1中stu1的hashcode:" + s1.getStu().hashCode());
        School s2 = s1.clone(); // 调用重写的clone方法,clone出一个新的school---s2
        System.out.println("s2: " + s2 + " s2的hashcode:" + s2.hashCode() + " s2中stu1的hashcode:" + s2.getStu().hashCode());

    }
}

s1和s2是不同的对象,但是他们包含的学生是同一个对象

s1: School [schoolName=实验小学, stuNums=100, stu=Student [name=zhangsan, age=20, sex=男]] s1的hashcode:366712642 s1中stu1的hashcode:1829164700
s2: School [schoolName=实验小学, stuNums=100, stu=Student [name=zhangsan, age=20, sex=男]] s2的hashcode:2018699554 s2中stu1的hashcode:1829164700

 

深拷贝

1 学生类实现cloneable接口

2 学生类重写clone方法

3 修改学校类的clone方法

public class Student implements Cloneable {

    private String name;
    private int age;
    private StringBuffer sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public StringBuffer getSex() {
        return sex;
    }

    public void setSex(StringBuffer sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", sex=" + sex + "]";
    }

    @Override
    protected Student clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return (Student) super.clone();
    }
}
public class School implements Cloneable {
    private String schoolName; // 学校名称
    private int stuNums; // 学校人数
    private Student stu; // 一个学生

    public String getSchoolName() {
        return schoolName;
    }

    public void setSchoolName(String schoolName) {
        this.schoolName = schoolName;
    }

    public int getStuNums() {
        return stuNums;
    }

    public void setStuNums(int stuNums) {
        this.stuNums = stuNums;
    }

    public Student getStu() {
        return stu;
    }

    public void setStu(Student stu) {
        this.stu = stu;
    }

    @Override
    protected School clone() throws CloneNotSupportedException {
        School s = null;
        s = (School) super.clone();
        s.stu = stu.clone();
        return s;
    }

    @Override
    public String toString() {
        return "School [schoolName=" + schoolName + ", stuNums=" + stuNums + ", stu=" + stu + "]";
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        School s1 = new School();
        s1.setSchoolName("实验小学");
        s1.setStuNums(100);
        Student stu1 = new Student();
        stu1.setAge(20);
        stu1.setName("zhangsan");
        stu1.setSex(new StringBuffer(""));
        s1.setStu(stu1);
        System.out.println("s1: " + s1 + " s1的hashcode:" + s1.hashCode() + "  s1中stu1的hashcode:" + s1.getStu().hashCode());
        School s2 = s1.clone(); // 调用重写的clone方法,clone出一个新的school---s2
        System.out.println("s2: " + s2 + " s2的hashcode:" + s2.hashCode() + " s2中stu1的hashcode:" + s2.getStu().hashCode());

        // 修改s2中的值,看看是否会对s1中的值造成影响
        s2.setSchoolName("希望小学");
        s2.setStuNums(200);
        Student stu2 = s2.getStu();
        stu2.setAge(30);
        stu2.setName("lisi");
        stu2.setSex(stu2.getSex().append("6666666"));
        s2.setStu(stu2);

        // 再次打印两个school,查看结果
        System.out.println("-------------------------------------------------------------------------");
        System.out.println("s1: " + s1 + " hashcode:" + s1.hashCode() + "  s1中stu1的hashcode:" + s1.getStu().hashCode());
        System.out.println("s2: " + s2 + " hashcode:" + s2.hashCode() + " s2中stu1的hashcode:" + s2.getStu().hashCode());

    }
}

 

s1: School [schoolName=实验小学, stuNums=100, stu=Student [name=zhangsan, age=20, sex=男]] s1的hashcode:366712642 s1中stu1的hashcode:1829164700
s2: School [schoolName=实验小学, stuNums=100, stu=Student [name=zhangsan, age=20, sex=男]] s2的hashcode:2018699554 s2中stu1的hashcode:1311053135
-------------------------------------------------------------------------
s1: School [schoolName=实验小学, stuNums=100, stu=Student [name=zhangsan, age=20, sex=男6666666]] hashcode:366712642 s1中stu1的hashcode:1829164700
s2: School [schoolName=希望小学, stuNums=200, stu=Student [name=lisi, age=30, sex=男6666666]] hashcode:2018699554 s2中stu1的hashcode:1311053135

 

可以修改s2中的性别,s1的也发生了改变,原因在于sex的类型是Stringbuffer,属于引用类型,在clone的时候将StringBuffer对象的地址传递了过去

这种情况应该怎么解决呢?

修改学生类的clone方法,设置sex时创建一个新的StringBuffer对象

浅拷贝,深拷贝