Skip to content

Java Programming

An Introduction to Cloning In Java

The term Cloning refers to creating duplicate copies. In software parlance it describes a number of processes that can be used to produce identical copies of an object. Java provides us an interface named java.lang.Cloneable, which does the same thing i.e. it creates an exact copy of the original object. In Java, it refers to creating an object with similar state as the original object.

The dictionary meaning of cloning is: Make an identical copy.

By default, Java cloning is field-for-field copy. The Object class in Java does not know about the structure of class on which clone() method will be invoked. So when we perform cloning in Java, JVM carries out the following action:

  • If the object/class has only primitive data type then a completely new copy of the object will be created and the reference to that object (new one) will be returned.
  • If the object/class contains members of any type then only the object/class references to those members are copied due to which the member references in both the original object as well as the cloned refers to the same object.

This behavior is by default and at any point you can always override this behavior and specify yours. In order to specify your own behavior you need to override a method named as clone().

In order to implement cloning in your class you need to implement java.lang.Cloneable interface which is also known as marker interface as it does not specify or declare any methods in it. An interface is called a marker interface when it adds a special behavior to the class implementing it at runtime and they do not have any method declarations. Marker interface is also known as tag interface and is a design pattern in computer science, used with many languages that provide runtime information about the objects.

A Class/Object implements the java.lang.Cloneable interface just to indicate to the method that it is legal for that method to make a field-for-field copy of instances of that class.

If you try to invoke Object’s clone method on an instances of a class that does not implement the java.lang.Cloneable interface then this will lead to an exception known as CloneNotSupportedException.

Class implementing java.lang.Cloneable interface must override Object’s clone method (which is by default protected) with a public method. As java.lang.Cloneable interface is a marker/tag interface so it does not contain the clone method. Therefore, it is not possible to clone an object merely by virtue of the fact that it implements this interface. Even if the clone method is invoked reflectively, there is no guarantee that it will succeed.

 

img-1

Original Java Object

 

Shallow Copy

By default, java creates a new instance of the same class and copies all the fields to the new instance and return it, this is know as Shallow copy.

img2

Shallow copy object obj1

 

 

 

 

 

 

Deep Copy

In order to get a deep copy of your object you need to override the clone method. When the copied object contains some other object its references are copied recursively in deep copy.

obj2 is Deep Copy of obj1

obj2 is Deep Copy of obj1

Rules defines the following

  1. “x.clone() != x” defines that the clone of object should not hold the same memory address as the original one and also guarantees that cloned object will have a separate memory address assignment.
  2. “x.clone().getClass() == x.getClass()”, defines that the cloned object and the original object should be of the same type and suggests that original and cloned objects should have same class type, but it is not mandatory.
  3. “x.clone().equals(x)” defines that the cloned object data should be equal to the original one and suggests that original and cloned objects should be equal using equals method.

Rules (ii) and (iii) are not absolute requirements as because when we shallow copy the object and if the object hold any references to some other object, then the references are copied and the cloned copy data or original object data can change at any point of time.

Example of Cloning a Trooper

Trooper.java

public class TrooperClone implements Cloneable{

int helmets;

int armor;

String war;

int lego;

String battle;

String Drawings;

public TrooperClone(int helmets, int armor, String war, int lego,

String battle, String drawings) {

super();

this.helmets = helmets;

this.armor = armor;

this.war = war;

this.lego = lego;

this.battle = battle;

Drawings = drawings;

}

public int getHelmets() {

return helmets;

}

public void setHelmets(int helmets) {

this.helmets = helmets;

}

public int getArmor() {

return armor;

}

public void setArmor(int armor) {

this.armor = armor;

}

public String getWar() {

return war;

}

public void setWar(String war) {

this.war = war;

}

public int getLego() {

return lego;

}

public void setLego(int lego) {

this.lego = lego;

}

public String getBattle() {

return battle;

}

public void setBattle(String battle) {

this.battle = battle;

}

public String getDrawings() {

return Drawings;

}

public void setDrawings(String drawings) {

Drawings = drawings;

}

@Override

protected TrooperClone clone() throws CloneNotSupportedException {

return (TrooperClone) super.clone();

}

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result

+ ((Drawings == null) ? 0 : Drawings.hashCode());

result = prime * result + armor;

result = prime * result + ((battle == null) ? 0 : battle.hashCode());

result = prime * result + helmets;

result = prime * result + lego;

result = prime * result + ((war == null) ? 0 : war.hashCode());

return result;

}

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

TrooperClone other = (TrooperClone) obj;

if (Drawings == null) {

if (other.Drawings != null)

return false;

} else if (!Drawings.equals(other.Drawings))

return false;

if (armor != other.armor)

return false;

if (battle == null) {

if (other.battle != null)

return false;

} else if (!battle.equals(other.battle))

return false;

if (helmets != other.helmets)

return false;

if (lego != other.lego)

return false;

if (war == null) {

if (other.war != null)

return false;

} else if (!war.equals(other.war))

return false;

return true;

}

@Override

public String toString() {

return "TrooperClone [helmets=" + helmets + ", armor=" + armor

+ ", war=" + war + ", lego=" + lego + ", battle=" + battle

+ ", Drawings=" + Drawings + "]";

}

}

JavaTrooperCloneTest.java

import org.apache.log4j.Logger;
/**

* Simple example of overriding clone() method in Java to understand How Cloning of

* Object works in Java.

*/

public class JavaTrooperCloneTest {

private static final Logger logger = Logger.getLogger(JavaTrooperCloneTest.class);


public static void main(String args[]) {
 

TrooperClone trooperClone = new TrooperClone(30, 50, "Drawing", 40, "Battle", "War");

logger.info(trooperClone);

TrooperClone copyofTrooper = null;

try {

logger.info("Creating Copy of Trooper using Clone method");

copyofTrooper = trooperClone.clone();

logger.info("Copy " + copyofTrooper);

 

} catch (CloneNotSupportedException ex) {

logger.debug("Cloning not supported for this object");

}
//testing properties of object returned by clone method in Java

logger.info("copyofTrooper != trooperClone : " + (copyofTrooper != trooperClone));

logger.info("copyofTrooper.getClass() == trooperClone.getClass() : " + (copyofTrooper.getClass() == trooperClone.getClass()));

logger.info("copyofTrooper.equals(trooperClone) : " + copyofTrooper.equals(trooperClone));


//Updating fields in original object

trooperClone.setArmor(20);

trooperClone.setBattle("Trooper Battle");

trooperClone.setDrawings("Trooper Drawing");

trooperClone.setHelmets(20);

trooperClone.setLego(20);

trooperClone.setWar("Trooper War");

logger.info("Original object :" + trooperClone);

logger.info("Clonned object  :" + copyofTrooper);

  }

}

Output

output

You can read more about this topic at Oracle.com Java docs. Hope this article enriches you with a fair idea of Cloning in Java. Feel free to share your views in the comment section.

 

Be Sociable, Share!
    The following two tabs change content below.

    Basant Singh

    Basant is a talented software developer who is very engaged in web & cloud platforms on a daily basis. He is a contributor to codingthis.com reporting on various news and troubleshooting on various platforms. Basant is very strong in SQL and a great asset to the CodingThis community.

    Latest posts by Basant Singh (see all)