Java Shallow Cloning and Deep Cloning

Shallow cloning

In shallow cloning, if the member variables of the prototype object are value types (basic data types such as int, double, byte, boolean, char), copy the data to the cloned object; if the member variables of the prototype object are reference types (complex data types such as classes, interfaces, arrays), copy the address of the reference object. Give cloned objects, that is, the member variables of prototype objects and cloned objects point to the same memory address.

Deep cloning

In deep cloning, whether the member variables of the prototype object are value type or reference type, a copy will be copied to the cloned object. In deep cloning, all reference objects of the prototype object will also be copied to the cloned object.

clone Method and Cloneable Interface in java

In java, all classes inherit the java.long.Object class. Clone method is provided in the Object class, which can copy a Java object. Therefore, the clone method provided by Object can be used directly to realize shallow cloning of objects.
However, it is important to note that a Cloneable interface is defined in java to indicate that a class can be cloned. If a class does not implement the Cloneable interface but calls the clone method, a CloneNotSuportedException exception will be thrown.

clone method in java satisfies the following points

  • For any object x, there is x.clone()!=x, and the cloned object is not the same object as the prototype object.
  • For any object x, there is x.clone().getClass()==x.getClass(). That is, the cloned object has the same type as the prototype object.

The clone method of Object class is used to obtain a cloned object of an object. The steps are as follows.

  • clone() method covering base class in derived class
  • Call super.clone() in the clone() method of the derived class
  • Derived classes require a Cloneable interface beforehand

Example

There is a report that contains an attachment with page number attributes.

Examples of shallow cloning

Annex Category

package cn.kevinlu98.blog.shallowclone;

/**
 * @Author: Kevin·Lu
 * @Date: 1:40 PM 2019/8/13
 * @Description: Enclosure
 */
public class Enclosure {
    // Annex Name
    private String name;

    public String getName() {
        return name;
    }

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

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

Reporting category

package cn.kevinlu98.blog.shallowclone;

/**
 * @Author: Kevin·Lu
 * @Date: 1:39 PM 2019/8/13
 * @Description: Presentation
 */
public class Report implements Cloneable {
    //The number of pages
    private int page;
    //Enclosure
    private Enclosure enclosure;

    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public Enclosure getEnclosure() {
        return enclosure;
    }

    public void setEnclosure(Enclosure enclosure) {
        this.enclosure = enclosure;
    }

    /**
     * Calling clone Method of Object Class to Realize Shallow Copy
     *
     * @return
     */
    @Override
    protected Report clone() {
        try {
            return (Report) super.clone();
        } catch (CloneNotSupportedException e) {
            System.out.println("This object does not support replication");
            return null;
        }
    }

    @Override
    public String
    toString() {
        return "Report{" +
                "page=" + page +
                ", enclosure=" + enclosure +
                '}';
    }
}

Test class

package cn.kevinlu98.blog.shallowclone;

/**
 * @Author: Kevin·Lu
 * @Date: 1:45 PM 2019/8/13
 * @Description:
 */
public class Client {
    public static void main(String[] args) {
        //Create Annex A
        Enclosure enclosureA = new Enclosure();
        enclosureA.setName("Enclosure A");
        //Create Report A
        Report reportA = new Report();
        reportA.setEnclosure(enclosureA);
        reportA.setPage(10);
        //Creating Report B through clone
        Report reportB = reportA.clone();
        System.out.println("reportA == reportB :" + (reportA == reportB));
        System.out.println("reportA.getEnclosure() == reportB.getEnclosure() :" + (reportA.getEnclosure() == reportB.getEnclosure()));

        //Setting the properties of report B
        reportB.getEnclosure().setName("Enclosure B");
        reportB.setPage(20);

        System.out.println(reportA);
        System.out.println(reportB);
    }
}

Result

Deep copy examples

We are now modifying the code to make deep copies.

Attachment classes require serialized instances, so we need to inherit the Serializable interface

package cn.kevinlu98.blog.deepclone;

import java.io.Serializable;

/**
 * @Author: Kevin·Lu
 * @Date: 1:40 PM 2019/8/13
 * @Description: Enclosure
 */
public class Enclosure implements Serializable {
    // Annex Name
    private String name;

    public String getName() {
        return name;
    }

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

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

Reporting category,

package cn.kevinlu98.blog.deepclone;

import java.io.*;

/**
 * @Author: Kevin·Lu
 * @Date: 1:39 PM 2019/8/13
 * @Description: Presentation
 */
public class Report implements Serializable {
    //The number of pages
    private int page;
    //Enclosure
    private Enclosure enclosure;

    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public Enclosure getEnclosure() {
        return enclosure;
    }

    public void setEnclosure(Enclosure enclosure) {
        this.enclosure = enclosure;
    }

    /**
     * Using serialization technology to achieve deep cloning
     *
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public Report deepClone() throws IOException, ClassNotFoundException {
        //Write objects into streams
        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bao);
        oos.writeObject(this);
        //Remove objects from the stream
        ByteArrayInputStream bis = new ByteArrayInputStream(bao.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return (Report) ois.readObject();
    }

    @Override
    public String
    toString() {
        return "Report{" +
                "page=" + page +
                ", enclosure=" + enclosure +
                '}';
    }
}

Test startup class

package cn.kevinlu98.blog.deepclone;

import java.io.IOException;

/**
 * @Author: Kevin·Lu
 * @Date: 1:45 PM 2019/8/13
 * @Description:
 */
public class Client {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //Create Annex A
        Enclosure enclosureA = new Enclosure();
        enclosureA.setName("Enclosure A");
        //Create Report A
        Report reportA = new Report();
        reportA.setEnclosure(enclosureA);
        reportA.setPage(10);
        //Creating Report B through clone
        Report reportB = reportA.deepClone();
        System.out.println("reportA == reportB :" + (reportA == reportB));
        System.out.println("reportA.getEnclosure() == reportB.getEnclosure() :" + (reportA.getEnclosure() == reportB.getEnclosure()));

        //Setting the properties of report B
        reportB.getEnclosure().setName("Enclosure B");
        reportB.setPage(20);

        System.out.println(reportA);
        System.out.println(reportB);
    }
}

Result

Tags: Programming Java

Posted on Mon, 12 Aug 2019 23:21:13 -0700 by polybiosis