Cloning using a copy constructor and implementing Clonable interface


Cloning using a copy constructor

An easy way to clone an object is by implementing a copy constructor.

public class CustomSheepExample {
    private String sheepName;
    private int sheepWeight;
 
    public CustomSheepExample(String name, int weight) {
        this.sheepName = name;
        this.sheepWeight = weight;
    }
 
    // Custom copy constructor
    public CustomSheepExample(CustomSheepExample other) {
        this.sheepName = other.sheepName;
        this.sheepWeight = other.sheepWeight;
    }
 
    public static void main(String[] args) {
        // Create a sheep
        CustomSheepExample originalSheep = new CustomSheepExample("Fluffy", 25);
 
        // Clone the sheep
        CustomSheepExample clonedSheep = new CustomSheepExample(originalSheep);
 
        // Display the details of the cloned sheep
        System.out.println("Cloned sheep - Name: " + clonedSheep.sheepName + ", Weight: " + clonedSheep.sheepWeight);
    }
}

Cloning by implementing Clonable interface

Cloning an object by implementing the Cloneable interface.

public class CustomSheepCloneExample implements Cloneable {
    private String sheepName;
    private int sheepWeight;
 
    public CustomSheepCloneExample(String name, int weight) {
        this.sheepName = name;
        this.sheepWeight = weight;
    }
 
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
 
    public static void main(String[] args) {
        // Create a sheep
        CustomSheepCloneExample originalSheep = new CustomSheepCloneExample("Buddy", 30);
 
        try {
            // Clone the sheep
            CustomSheepCloneExample clonedSheep = (CustomSheepCloneExample) originalSheep.clone();
 
            // Display the details of the cloned sheep
            System.out.println("Cloned sheep - Name: " + clonedSheep.sheepName + ", Weight: " + clonedSheep.sheepWeight);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

Cloning performing a shallow copy

Default behavior when cloning an object is to perform a shallow copy of the object's fields. In that case, both the original object and the cloned object, hold references to the same objects.

This example shows that behavior.

import java.util.List;
import java.util.ArrayList;
 
public class CustomSheepCloneExample implements Cloneable {
    private String sheepName;
    private int sheepWeight;
    private List<CustomSheepCloneExample> offspring;
 
    public CustomSheepCloneExample(String name, int weight) {
        this.sheepName = name;
        this.sheepWeight = weight;
    }
 
    @Override
    public Object clone() throws CloneNotSupportedException {
        // Calling super.clone() for shallow copy
        CustomSheepCloneExample clonedSheep = (CustomSheepCloneExample) super.clone();
 
        // Deep copy for the List of offspring
        if (offspring != null) {
            clonedSheep.offspring = new ArrayList<>();
            for (CustomSheepCloneExample child : offspring) {
                clonedSheep.offspring.add((CustomSheepCloneExample) child.clone());
            }
        }
 
        return clonedSheep;
    }
 
    public List<CustomSheepCloneExample> getOffspring() {
        return offspring;
    }
 
    public void setOffspring(List<CustomSheepCloneExample> offspring) {
        this.offspring = offspring;
    }
 
    public static void main(String[] args) {
        // Create a sheep
        CustomSheepCloneExample originalSheep = new CustomSheepCloneExample("Fluffy", 25);
 
        // Create children
        CustomSheepCloneExample child1 = new CustomSheepCloneExample("Child1", 4);
        CustomSheepCloneExample child2 = new CustomSheepCloneExample("Child2", 5);
 
        // Set children for the original sheep
        originalSheep.setOffspring(List.of(child1, child2));
 
        try {
            // Clone the sheep
            CustomSheepCloneExample clonedSheep = (CustomSheepCloneExample) originalSheep.clone();
 
            // Verify if the children lists are not the same objects in memory
            List<CustomSheepCloneExample> originalOffspring = originalSheep.getOffspring();
            List<CustomSheepCloneExample> clonedOffspring = clonedSheep.getOffspring();
 
            for (int i = 0; i < originalOffspring.size(); i++) {
                // prints true if both lists contain equivalent but different objects
                System.out.println(originalOffspring.get(i) == clonedOffspring.get(i));
            }
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

Basic Programs