Java 的深拷贝和浅拷贝学习
  anLrwkgbyYZS 2023年12月30日 8 0


1. 为什么需要拷贝

举一个例子,一个Student类,初始化创建一个student01实例,如果想让初始化创建student02实例和student01实例相同,你可能会这样做:Student student02 = student01,直接赋值。这样做是有问题的,student01这个对象实例放在Java堆中,如果你直接赋值,Java堆中并没有创建一个新的实例对象student02,而是让student02变量直接指向Java堆中的student01实例,如果你修改student02 或 student01 中任何一个对象实例,就是修改了Java堆中的那个唯一实例,另外一个对象实例也会随之改变,接下来我们用程序来测试一下。

首先创建一个Student类,代码如下所示:

package clone;

public class Student {
    private String name;
    private int age;

    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;
    }

    @Override
    public String toString() {
        return "MyCloneStudy{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

初始化创建一个student01实例,然后通过Student student02 = student01来初始化创建student02实例,修改其中一个,然后查看另外一个的值是否改变。测试代码如下所示:

package clone;

public class MyCloneStudy {
    public static void main(String args[]) {
        Student student01 = new Student();
        student01.setName("syrdbt");
        student01.setAge(21);
        System.out.println(student01);
        Student student02 = student01;
        System.out.println(student02);

        System.out.println("修改student01:");
        student01.setName("Jack");
        student01.setAge(200);
        System.out.println(student01);
        System.out.println(student02);

        System.out.println("修改student02:");
        student01.setName("Rose");
        student01.setAge(18);
        System.out.println(student01);
        System.out.println(student02);
    }
}

运行截图如下所示,显然发生了上述的错误:

Java 的深拷贝和浅拷贝学习_ide

2. 浅拷贝

让Studen类实现 Cloneable 接口,Cloneable 接口是一个标识接口,实现了这个接口之后才可以调用Object类的clone方法,然后在Student类中重写clone方法,即可实现浅拷贝。代码如下所示。

Student类实现 Cloneable 接口,重写clone方法。

package clone;

public class Student implements Cloneable{
    private String name;
    private int age;

    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;
    }

    @Override
    public String toString() {
        return "MyCloneStudy{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    protected Object clone(){
        Object object = null;
        try {
            object = super.clone();
        } catch (CloneNotSupportedException c) {
            c.printStackTrace();
        }
        return object;
    }


}

测试代码如下所示 ,通过student02 = (Student) student01.clone()来实现浅拷贝。

package clone;

public class MyCloneStudy {
    public static void main(String args[]) {
        Student student01 = new Student();
        student01.setName("syrdbt");
        student01.setAge(21);
        System.out.println(student01);
        Student student02 = null;

        student02 = (Student) student01.clone();

        System.out.println(student02);

        System.out.println("修改student01:");
        student01.setName("Jack");
        student01.setAge(200);
        System.out.println(student01);
        System.out.println(student02);

        System.out.println("修改student02:");
        student01.setName("Rose");
        student01.setAge(18);
        System.out.println(student01);
        System.out.println(student02);
    }
}

运行截图如下所示

Java 的深拷贝和浅拷贝学习_ide_02

3. 深拷贝

浅拷贝有问题吗?显然是有问题的,看下面这个例子,把name这个属性修改成一个类。

Name类代码如下所示:

package clone;

public class Name {
    private String name;

    public Name(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

Student 类如下所示:

package clone;

public class Student implements Cloneable{
    private Name name;
    private int age;

    public Name getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name=" + name.getName() +
                ", age=" + age +
                '}';
    }

    @Override
    protected Object clone(){
        Object object = null;
        try {
            object = super.clone();
        } catch (CloneNotSupportedException c) {
            c.printStackTrace();
        }
        return object;
    }
}

测试代码:

package clone;

public class MyCloneStudy {
    public static void main(String args[]) {
        Name name = new Name("syrdbt");

        Student student01 = new Student();
        student01.setName(name);
        student01.setAge(21);
        System.out.println(student01);
        Student student02 = (Student) student01.clone();
        System.out.println(student02);

        System.out.println("修改Name为Jack:");
        name.setName("Jack");
        System.out.println(student01);
        System.out.println(student02);
    }
}

运行测试代码,你会发现浅拷贝的错误,修改完Name之后,Student01和Student02的name都改变了。

Java 的深拷贝和浅拷贝学习_浅拷贝_03

如何解决这个问题,在Student类中将Name成员变量也进行拷贝。

Name 类实现了浅拷贝:

package clone;

public class Name implements Cloneable{
    private String name;

    public Name(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    @Override
    protected Object clone(){
        Object o = null;
        try {
            o = super.clone();
        } catch (CloneNotSupportedException c) {
            c.printStackTrace();
        }
        return o;
    }
}

Student 类实现了深拷贝:

package clone;

public class Student implements Cloneable{
    private Name name;
    private int age;

    public Name getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name=" + name.getName() +
                ", age=" + age +
                '}';
    }

    @Override
    protected Object clone(){
        Student student = null;
        try {
            student = (Student) super.clone();
        } catch (CloneNotSupportedException c) {
            c.printStackTrace();
        }
        student.name = (Name) name.clone();
        return student;
    }
}

测试代码,如下所示:

package clone;

public class MyCloneStudy {
    public static void main(String args[]) {
        Name name = new Name("syrdbt");

        Student student01 = new Student();
        student01.setName(name);
        student01.setAge(21);
        System.out.println(student01);
        Student student02 = (Student) student01.clone();
        System.out.println(student02);

        System.out.println("修改Name为Jack:");
        name.setName("Jack");
        System.out.println(student01);
        System.out.println(student02);
    }
}

运行结果,显然解决了“修改完Name之后,Student01和Student02的name都改变”这个问题。

Java 的深拷贝和浅拷贝学习_ide_04

 

END。

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月30日 0

暂无评论

推荐阅读
  anLrwkgbyYZS   2023年12月30日   7   0   0 ideciciMaxideMax
anLrwkgbyYZS