Ullas
Ullas

Reputation: 837

How does the Java clone method work?

public class Student implements Cloneable {
    public Student clone() {
        Student clonedStudent = (Student) super.clone();
        return clonedStudent;
    }
}

Why does Java return student object instead of returning object class object. As we are using super. Does it mean Java itself provides shallow cloning in the clone method?

Upvotes: 8

Views: 10978

Answers (4)

Animesh Prosad
Animesh Prosad

Reputation: 519

java.lang.Object provides default implementation of clone() method in Java. It's declared as protected and native in Object class, so implemented in native code. Since its convention to return clone() of an object by calling super.clone() method, any cloning process eventually reaches to java.lang.Object clone() method. This method, first checks if the corresponding object implements Cloneable interface, which is a marker interface. If that instance doesn't implement Cloneable then it throws CloneNotSupportedException in Java, a checked exception, which is always required to be handled while cloning an object. In java, if a class needs to support cloning it has to do following things:

A) You must implement Cloneable interface. B) You must override clone() method from Object class. [It's weird. clone() method should have been in Cloneable interface.]

Java docs about clone() method are given below (formatted and extract). /* Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object. The general intent is that, for any object x, the expression: 1) x.clone() != x will be true //guarantees that cloned object will have separate memory address assignment. 2) x.clone().getClass() == x.getClass() will be true, but these are not absolute requirements.//original and cloned objects should have same class type, but it is not mandatory. 3) x.clone().equals(x) will be true, this is not an absolute requirement.//original and cloned objects should have be equal using equals() method, but it is not mandatory. */

Lets see an Example :

public class MyClone {
    int x;
    public static void main(String[] args) throws
       CloneNotSupportedException {
        MyClone c = new MyClone();
        MyClone a = (MyClone) c.clone();  // Type-cast is required
    }
}

Because clone() is a part of the Object class, and Object won't implement the Cloneable interface, when our own class will not implement the Cloneable interface, the JVM will not know that this class is eligible for cloning, so CloneNotSupportedException comes out.

Only two thing are possible when we say MyClone a = (MyClone) c.clone();:

Either it will return the cloned object.

Or it will throw CloneNotSupportedException.

As it is clear that it is not mandatory to implement clone() in your class when you want to clone the object, if you don't, the clone() method in Object class is declared protected — only subclasses and members of the same package will be able to invoke clone() on the object. If you want to change that, you should override it and make it public.

Checks before the clone() method call:

if(c instanceof Cloneable) {
    MyClone a = (MyClone) c.clone();
}

Note: No constructor gets called when clone() gets called. It's our responsibility to properly set all the member variables of that class.

Implementation:

Room.java
public class Room {
 private String roomSize;
 public Room(String roomSize){
  this.roomSize = roomSize;
}
 //Any Getters-Setters go here
}
Flat.java
public class Flat implements Cloneable {
 private String flatNumber;
 private Room room;
 public Flat(String size,Room room){
   this.size = size;
   this.room = room;
 }
 public Object clone() {
  try {
   return (Flat)super.clone();
 }
  catch (CloneNotSupportedException e) {
   System.out.println("CloneNotSupportedException comes out : "
   +e.getMessage());
  }
 }
//Any Getters-Setters go here
}
Main.java
public class Main {
  public static void main(String[] args) {
   Room room = new Room("40 X 40");
   Flat flat1 = new Flat(403 , room);
   Flat flat2 = (Flat)flat1.clone();
  }
}

Here super.clone() is getting called inside clone(). As we know, clone() is declared in Object, so it is inherited by every Java object. Calling super.clone() copies our superclass' fields and makes bitwise copies of the fields. This known as shallow copy, which means when you copy Flat using clone(), the field's flatNumber is getting copied with their respective values, but room is copied by reference — bit by bit, the memory address is getting copied.

Any changes you make to room of the original object will be reflected in the cloned object and vice versa. To solve this, we need deep copy. Now, we need to change the Room class as well implement the Cloneable interface and clone() method, then call the clone() method of the Room object inside the clone() method of the Flat object.

New Implementation

Room.java
public class Room {
    private String roomSize;
    public Room(String roomSize){
       this.roomSize = roomSize;
   }
    public Object clone() {
       try {
         return (Room)super.clone();
     }
      catch (CloneNotSupportedException e) {
       System.out.println("CloneNotSupportedException comes out : "
    +e.getMessage());
     }
   }
   //Any Getters-Setters go here
}
Flat.java
public class Flat implements Cloneable {
    private String flatNumber;
 private Room room;
 public Flat(String size,Room room){
   this.size = size;
   this.room = room;
 }
    public Object clone() {
      Flat flat = null;
      try {
         flat = (Flat)super.clone();
     }
      catch (CloneNotSupportedException e) {
          System.out.println("CloneNotSupportedException comes out : "
    +e.getMessage());
     }
     flat.room = (Room) room.clone();
         return flat;
   }
    //Any Getters-Setters go here
}
Main.java
public class Main {
    public static void main(String[] args) {
       Room room = new Room("40 X 40");
       Flat flat1 = new Flat(403, room);
       Flat flat2 = (Flat)flat1.clone();
   }
}

I hope that this will give a better understanding of cloning and its implementation.

Thanks to http://interviewguess.blogspot.in/2017/02/how-does-clone-method-work.html

Upvotes: 2

swapy
swapy

Reputation: 1616

clone() method acts like a copy constructor.

It creates and returns a copy of the object. Since the Object class has the clone method (protected) you cannot use it in all your classes. The class which you want to be cloned should implement clone method and overwrite it. It should provide its own meaning for copy or to the least it should invoke the super.clone(). Also you have to implement Cloneable marker interface or else you will get CloneNotSupportedException. When you invoke the super.clone() then you are dependent on the Object class’s implementation and what you get is a shallow copy.

You can reffer Wiki Pagefor more understanding.

For cloning object one should implement Interface Cloneable

If you are trying to use the clone method in a class where Cloneable interface is not implemented, it throws CloneNotSupportedException.

Upvotes: 4

Maroun
Maroun

Reputation: 96018

See what the docs say about it:

... Thus, this method performs a "shallow copy" of this object, not a "deep copy" operation.

Also see this link:

if the class has only primitive data type members then a completely new copy of the object will be created and the reference to the new object copy will be returned. But, if the class contains members of any class type then only the object references to those members are copied and hence the member references in both the original object as well as the cloned object refer to the same object.

Upvotes: 9

bNd
bNd

Reputation: 7640

java cloning is field by field copy i.e. as the Object class does not have idea about the structure of class on which clone() method will be invoked.

1) If the class has only primitive data type members then a completely new copy of the object will be created and the reference to the new object copy will be returned.

2) If the class contains members of any class type then only the object references to those members are copied and hence the member references in both the original object as well as the cloned object refer to the same object.

Refer this link object cloning in java

Upvotes: 13

Related Questions