1. 深拷贝和浅拷贝

一、 浅拷贝(Shallow Copy)

1. 浅拷贝介绍

浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。即默认拷贝构造函数只是对对象进行浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源。

2. 浅拷贝特点

(1) 对于基本数据类型的成员对象,因为基础数据类型是值传递的,所以是直接将属性值赋值给新的对象。基础类型的拷贝,其中一个对象修改该值,不会影响另外一个。
(2) 对于引用类型,比如数组或者类对象,因为引用类型是引用传递,所以浅拷贝只是把内存地址赋值给了成员变量,它们指向了同一内存空间。改变其中一个,会对另外一个也产生影响。

3. 浅拷贝的实现

3.1 使用实现Cloneable接口,重写clone()方法

/**
 * @author Liufei
 * @date 2020/3/15 6:24 下午
 */
public class Subject {
    private String name;
    public Subject(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "[Subject: " + this.hashCode() + ",name:" + name + "]";
    }
}
package com.yiyang.java.copy;

/**
 * @author Liufei
 * @date 2020/3/15 6:24 下午
 */
public class Student implements Cloneable {
    private Subject subject;
    private String name;
    private int age;
    public Subject getSubject() {
        return subject;
    }
    public void setSubject(Subject subject) {
        this.subject = subject;
    }
    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
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    @Override
    public String toString() {
        return "Student{" +
                this.hashCode() +
                ", subject=" + subject +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

package com.yiyang.java.copy;

/**
 * 浅拷贝
 * @author Liufei
 * @date 2020/3/15 6:23 下午
 */
public class ShallowCopyDemo {

    public static void main(String[] args) {
        Subject subject = new Subject("liufei");
        Student studentA = new Student();
        studentA.setSubject(subject);
        studentA.setName("张三");
        studentA.setAge(20);

        try {
            Student studentB = (Student) studentA.clone();
            studentB.setName("李四");
            studentB.setAge(18);
            Subject subjectB = studentB.getSubject();
            subjectB.setName("王五");
            System.out.println("studentA: " + studentA.toString());
            System.out.println("studentB: " + studentB.toString());
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

3.2 使用构造方法实现浅拷贝

1. Subject类和上面的一样
2.
package com.yiyang.java.copy;

/**
 * @author Liufei
 * @date 2020/3/15 6:57 下午
 */
public class Student2 {
    private Subject subject;
    private String name;
    private int age;
    public Student2() {

    }
    public Student2(Student2 student2) {
        this.name = student2.name;
        this.age = student2.age;
        this.subject = student2.subject;
    }
    public Subject getSubject() {
        return subject;
    }
    public void setSubject(Subject subject) {
        this.subject = subject;
    }
    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
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    @Override
    public String toString() {
        return "Student{" +
                this.hashCode() +
                ", subject=" + subject +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
package com.yiyang.java.copy;

/**
 * @author Liufei
 * @date 2020/3/15 6:59 下午
 */
public class ShallowCopyDemo2 {

    public static void main(String[] args) {
        Student2 student1 = new Student2();
        student1.setName("zhangsan");
        student1.setAge(18);
        Subject subject = new Subject("subject");
        student1.setSubject(subject);
        Student2 student2 = new Student2(student1);
        System.out.println("student1: " + student1);
        System.out.println("student2: " + student2);
        // 修改后
        student2.setName("李四");
        student2.setAge(20);
        System.out.println("修改后 -> student1: " + student1);
        System.out.println("修改后 -> student2: " + student2);
    }
}

二、 深拷贝
深拷贝,在拷贝引用类型成员变量时,为引用类型的数据成员另辟了一个独立的内存空间,实现真正内容上的拷贝。

2. 深拷贝特点

(1) 对于基本数据类型的成员对象,因为基础数据类型是值传递的,所以是直接将属性值赋值给新的对象。基础类型的拷贝,其中一个对象修改该值,不会影响另外一个(和浅拷贝一样)。
(2) 对于引用类型,比如数组或者类对象,深拷贝会新建一个对象空间,然后拷贝里面的内容,所以它们指向了不同的内存空间。改变其中一个,不会对另外一个也产生影响。
(3) 对于有多层对象的,每个对象都需要实现 Cloneable 并重写 clone() 方法,进而实现了对象的串行层层拷贝。
(4) 深拷贝相比于浅拷贝速度较慢并且花销较大。

3. 代码实现

3.1 使用cloneable()

package com.yiyang.java.copy;

/**
 * @author Liufei
 * @date 2020/3/15 6:24 下午
 */
public class Subject implements Cloneable {

    private String name;

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

    public String getName() {
        return name;
    }

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "[Subject: " + this.hashCode() + ",name:" + name + "]";
    }
}
package com.yiyang.java.copy;

/**
 * @author Liufei
 * @date 2020/3/15 6:24 下午
 */
public class Student implements Cloneable {

    private Subject subject;

    private String name;

    private int age;

    public Subject getSubject() {
        return subject;
    }

    public void setSubject(Subject subject) {
        this.subject = subject;
    }

    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
    protected Object clone() throws CloneNotSupportedException {
        Student clone = (Student) super.clone();
        clone.subject = (Subject) subject.clone();
        return clone;
    }

    @Override
    public String toString() {
        return "Student{" +
                this.hashCode() +
                ", subject=" + subject +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
package com.yiyang.java.copy;

/**
 * 浅拷贝
 * @author Liufei
 * @date 2020/3/15 6:23 下午
 */
public class ShallowCopyDemo {

    public static void main(String[] args) {
        Subject subject = new Subject("liufei");
        Student studentA = new Student();
        studentA.setSubject(subject);
        studentA.setName("张三");
        studentA.setAge(20);

        try {
            Student studentB = (Student) studentA.clone();
            studentB.setName("李四");
            studentB.setAge(18);
            Subject subjectB = studentB.getSubject();
            subjectB.setName("王五");
            System.out.println("studentA: " + studentA.toString());
            System.out.println("studentB: " + studentB.toString());
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

3.2 使用对象的序列化

package com.yiyang.java.copy;

import java.io.Serializable;

/**
 * @author Liufei
 * @date 2020/3/15 6:24 下午
 */
public class Subject implements Serializable {

    public static final long serialVersionUID = 400L;

    private String name;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "[Subject: " + this.hashCode() + ",name:" + name + "]";
    }
}
package com.yiyang.java.copy;

import java.io.Serializable;

/**
 * @author Liufei
 * @date 2020/3/15 8:40 下午
 */
public class Student3 implements Serializable {

    public static final long serialVersionUID = 42L;

    private Subject subject;

    private String name;

    private int age;

    public Student3() {

    }

    public Subject getSubject() {
        return subject;
    }

    public void setSubject(Subject subject) {
        this.subject = subject;
    }

    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
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Student{" +
                this.hashCode() +
                ", subject=" + subject +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
package com.yiyang.java.copy;

import java.io.*;

/**
 * @author Liufei
 * @date 2020/3/15 8:42 下午
 */
public class ShallowCopyDemo3 {

    public static void main(String[] args){
        // 对象的序列化
        writeObject();
        readerObject();
    }

    /**
     * 对象的序列化
     */
    public static  void writeObject() {
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("student.txt"));
            Student3 student3 = new Student3();
            student3.setName("刘飞");
            student3.setAge(25);
            student3.setSubject(new Subject("李慧慧"));
            oos.writeObject(student3);

            oos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 对象的反序列化
     */
    public static void readerObject() {
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream("student.txt"));
            Student3 object = (Student3) ois.readObject();
            System.out.println(object);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (ois != null) {
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}




posted @ 2021-08-04 00:00  刘翊扬  阅读(58)  评论(0编辑  收藏  举报