Reputation: 837
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
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
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
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
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