Skip to main content

Command Palette

Search for a command to run...

Java Cloneable Mystery

Published
2 min readView as Markdown

Sometimes, very small and straightforward concepts become very complex and confuse you to the core. Cloneable interface and cloning as a concept in Java is one such concept.

Firstly, Cloneable is a marker interface meaning it contains no method. It just indicates that clone method present in Object class can be invoked on the class which implements Cloneable.

Secondly, the implementation of the Object clone() method can only be found in the jvm. There is no source code attached to the Object class for the clone() method. The use of the clone() method will throw a CloneNotSupportedException exception if a class doesn't implement the Cloneable interface.

Thirdly, the big confusion about shallow and deep cloning. The documentation always states that the cloning using Object.clone() is always shallow. However, it depends upon the member of the object class which is cloned.

  • If the class only contains immutable and primitive types then Object.clone() will return a deep copy.

  • If the class contains some mutable objects like array or ArrayList then Object.clone() will return shallow copy.

Here is program showing both shallow and deep copy.

package prototype.cloneable;

import java.util.ArrayList;
import java.util.List;

class Address implements Cloneable {
    private Integer streetName;
    private String cityName;

    public Address(Integer streetName, String cityName) {
        super();
        this.streetName = streetName;
        this.cityName = cityName;
    }

    public String getCityName() {
        return cityName;
    }

    public void setCityName(String cityName) {
        this.cityName = cityName;
    }

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

    @Override
    public String toString() {
        return "Address [streetName=" + streetName + ", cityName=" + cityName + "]";
    }
}

public class CloneExample {
    public static void main(String[] args) throws CloneNotSupportedException {
        // Shallow Copy
        Address s1 = new Address(123, "Delhi");
        Address s2 = (Address) s1.clone();
        s2.setCityName("Noida");

        // the change in s2 doesn't reflect in s1.
        System.out.println(s1);
        System.out.println(s2);

        // Deep Copy
        ArrayList<Address> list = new ArrayList<>();

        Address a1 = new Address(123, "Delhi");
        list.add(a1);

        ArrayList<Address> list1 = (ArrayList<Address>) list.clone();
        //update the a1 and set City to  
        a1.setCityName("Noida");

        System.out.println(list);
        System.out.println(list1);

    }
}

I want to end it by referring to blog from Joshua Bloch which explains why Clone is broken and alternatives to use. https://www.artima.com/articles/josh-bloch-on-design#part13