How to clone a Java object with the clone() method
I have a question regarding properly implementing the clone()
method for a class in java.
I know that this is bad practice, but I need to know this for an exam..
In the above discussion they say to call super.clone()
- but I don't udnerstand what happens if the super function doesn't implement Clonable.
For example, say I have a class X that extends Y. X implements Clonable and Y doesnl't. Y's clone()
method should throw an Exception. Then what do we do in this case?
All the explanations I could find somehow assume that all superclasses implement Clonable, or at least that's what I understood..
EDIT:
Check out this code please:
public class Employee implements Cloneable {
private String name;
public Employee(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Object clone()throws CloneNotSupportedException{
return (Employee)super.clone();
}
public static void main(String[] args) {
Employee emp = new Employee("Abhi");
try {
Employee emp2 = (Employee) emp.clone();
System.out.println(emp2.getName());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
It is taken from here: https://www.javacodegeeks.com/2018/03/understanding-cloneable-interface-in-java.html
Similar code can be found in many tutorials.
Why can they use super.clone()
when the superclass (which in this case is Object
) does not implement Clonable - that would result in an Exception.
If you have this structure:
class Y {}
class X extends Y implements Cloneable {
@Override
public X clone() {
try {
return (X) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}
}
Then clone on instances of X
will work fine.
It won't work on direct instances of Y
, because they are not declared cloneable. But the Cloneable
interface on X
is an indicator to the mechanisms of the default clone()
implementation that they should be made to work.
Alternatively
You could also have a non-Cloneable class with a working clone()
method, as long as you didn't rely on the default implementation of clone()
.
For instance:
class Y {
@Override
public Y clone() {
// Don't call super.clone() because it will error
return new Y(...); // whatever parameters
}
}
However, with this mechanism, if you called super.clone()
from a subclass of Y
, you would get an instance of Y
, which is probably not what you would want.
As others have pointed out, the Cloneable
mechanism is awkward and confusing, and usually copying mechanisms using new
are easier to work with.