I was trying to understand how Object.clone() works in Java. I came across the following facts:
- 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. - Invoking
Object
'sclone
method on an instance that does not implement theCloneable
interface results in the exceptionCloneNotSupportedException
being thrown. - However, note that the
Cloneable
interface does not contain theclone
method. Hence, implementingCloneable
is not responsible for raising any error / exception for not implementingclone()
. - Instead,
Object.clone()
is a native method, which callsJVM_Clone
fromjvm.cpp
andCloneNotSupportedException
is thrown in this cpp method.
Doubts:
Q1. Why did the Java designers make this design choice and implement it like this? Why not have clone()
defined in Cloneable
itself which will give a compile time error if the implementing class does not provide an implementation for clone()
.
Q2. Why check whether an instance implements Cloneable
at run time?
Q3. Is there any specific reason to check it in native code?
Q4. The weird thing is Object
itself does not implement Cloneable
, but provides an implementation of clone()
, which in turn checks whether any class implementing Cloneable
implements clone()
or not. Shouldn't ideally Object
implement Cloneable
(declaring clone()
) and then provide an implementation for clone()
?
PS: I know asking multiple questions in one question is a bad idea. But these are closely related questions. I could very well ask a single question like "Why does Cloneable
not contain clone()
?" But, I felt, to better answer this doubt, one must cover various subtle aspects of this design decision. I gave effort to think more and came up with possible different subtle aspects and asked them explicitly pointwise so that an answerer wont miss them and will give an overall complete answer.
The thing is that they wanted to provide a default implementation of the clone() method, but default methods didn't exist then, so they just had Object.clone and then the Cloneable interface to signify that it could be cloned. So it's really just that it's old.
As another user said before, the clone method is native and that modifier is also not allowed in interfaces. Making Cloneable an abstract class is not an option because you would be forced to extend it and not be able to extend other classes since Java doesn't really have multiple inheritance. Why clone isn't just supported for all objects, I don't know.