Super.clone () operation does not work in derived class
This is due to technical difficulties encountered in my project.
Problem: I need to clone a class object in which it has extended properties (inheritance) from a third party library class (where we don't have access to change its content).
Let me clarify below:
Parent class:
public class UnChangeableBaseClass {
//fields and Methods
}
Child class:
class DerivedLocalClass extends UnChangeableBaseClass implements Cloneable {
// local fields and methods
public Object clone(){
Object clonedObj= null;
try{
clonedObj = super.clone();
}
catch(CloneNotSupportedException e){
//log exceptions
}
}
}
When I try to do this, the method super.clone()
is of type Class - UnChangeableBaseClass
and does not override the methods Object clone()
. I believe all classes were extended with java.lang.Object class
, implicitly the protected Object clone()
method would be inherited for that parent class. So, I figured this method in Derived Class would override the parent / object cloning method. But at runtime, the JVM looks for a clone method explicitly defined in UnChangeableBaseClass
. I hope I explained correctly, not to confuse you.
My questions:
-
How can I implement the clone method in this typical case where we cannot add any method in the parent class to
super.clone()
call the object clone method. -
If the above case is not possible, is there another way to clone the derived class Object (considering all the limitations in the above scenario)
-
Finally, just to find out the reason behind this JVM behavior (described above).
source to share
The correct method signature is below
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
Clone is a method Protected
in a class Object
, so it is available to you inside the class, and if you extend from it.
super.clone()
you just need to call the method clone()
from the object that calls the internalClone
on method this
, which is the current class object.
internalClone((Cloneable) this);
So the above clone()
method inside Object
will only throw CloneNotSupportedException
if the instance it is being called on is notCloneable
I see some misconceptions about the cloning method
-
clone()
the method isProtected
inside the classObject
, so you cannot callclone()
outside the class. for examplechild.clone()
, if you don't override it and make accesspublic
-
Cloneable
is a marker interface and if you do not mark the classCloneable
then you will getCloneNotSupportedException
if you call the methodclone()
- If the class contains only primitive fields or references to immutable objects, then it usually happens that no fields in the returned object
super.clone
need to be changed. - By convention, the returned object must be obtained by calling
super.clone
. If a class and all of itsuperclasses (except Object)
obey this convention, it will be thatx.clone().getClass() == x.getClass()
.
So the code below works fine
public class Child extends UnChangeableBaseClass
implements
Cloneable {
int index = 0;
public Child(int index) {
this.index = 10;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Links:
source to share
How can I implement the clone method in this typical case where we cannot add any method to the parent class so that super.clone () will call Object clone.
Ok, since the method clone
is a protected method in the class Object
, so it is available in your superclass UnChangeableBaseClass
as well, since it is propagated from the class Object
. This way you can access the method clone
using super.clone()
, from your base class DerivedLocalClass
.
If the above case is not possible, is there any other way to clone the Derived Class Object (considering all the limitations of the above scenario)
I would suggest that even if you have the option to use a method clone
to clone an object, you shouldn't use it. It would be better to use in a derived class and add the call to the constructor of the base class. copy-constructor
super()
Also see Effective Java - Item#11 - Override clone judiciously
that suggest the method was clone
broken.
In this article: Josh Bloch on Design - Copy Constructor versus Cloning
you would like to see the first paragraph Bloch
: -
If you read the article on cloning in my book, especially if you read between the lines, you will know that I think the clone is deeply broken. There are several design flaws, the biggest of which is that the Cloned Interface has no cloning method. And that means it just doesn't work: doing something cloned doesn't say anything about what you can do about it. Instead, he says something about what he can do internally. It says that if you call super.clone repeatedly it ends up calling the object cloning method, that method will return a copy of the original field.
So the conclusion is that you can have copy constructor
in your DerivedLocalClass
, which will return you a copy of the caller, something like this: -
public DerivedLocalClass(DerivedLocalClass obj) {
this.setVar(obj.getVar());
}
source to share
JVM Cloning works using the Marker Cloneable interface rather than looking for Object.clone (). It is true that all Java classes inherit the clone method, but according to the javadoc for Cloneable
A class implements the Cloneable interface to indicate to the Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class.
In your case, you cannot do super.clone () because it is not marked as Cloneable. If you can't change the parent class, you'll have to make a copy yourself.
source to share
I am using java 1.7 and I am not getting any problem running the code given by the OP. If the superclass does not have an overridden clone to throw the exception, I think this should work even if the superclass does not declare itself to be cloned.
Note that
public Object clone()
does not override clone method, it lacks a throws clause.
source to share