There is something that I don't understand in the usual implementation of the clone method. If you look at the first line in the try block in the following code, we are calling super.clone(), which will create an instance of the of the super class, and return an Object reference to that instance. Now, that instance does not necessarily contain hireDay, so how are we saying copy.hireDay? It is true that it will compile fine, but shouldn't it crash if the instance does not contain hireDay?
public Object clone() {
try {
Employee copy = (Employee) super.clone(); // copy ID, name, and salary!
copy.hireDay = (Date) hireDay.clone();
return copy;
} catch (CloneNotSupportedException e) {
System.out.println(e);
return null;
}
}
The contract of clone
is to achieve the same calling pattern as with constructors: the first step is always to call the superclass implementation. This results in Object.clone
being invoked first and all subclasses use the instance returned by that method.
Object.clone
will return an instance of the same class as the one being cloned. This happens by extralinguistic magic, basically by a bitwise copy of the memory block + necessary changes to the copy.
The cloning mechanism is fragile because any noncompliant class in the ancestor chain breaks cloning for all its descendants. This is one of several reasons why this mechanism is disfavored.
clone()
is a special method in the base Object
class which creates a new instance of the correct base class type and copies all the fields (and avoids using any constructors). So, provided you don't have a custom parent class which does not delegate to Object.clone()
you will always get the current type back.
As a side note, in your example, if super.clone()
did not return an Employee
, then your code would throw ClassCastException before you even got to the step where you reference hireDay
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With