5

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's clone method on an instance that does not implement the Cloneable interface results in the exception CloneNotSupportedException being thrown.
  • However, note that the Cloneable interface does not contain the clone method. Hence, implementing Cloneable is not responsible for raising any error / exception for not implementing clone().
  • Instead, Object.clone() is a native method, which calls JVM_Clone from jvm.cpp and CloneNotSupportedException 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.

Boann
  • 48,794
  • 16
  • 117
  • 146
MsA
  • 2,599
  • 3
  • 22
  • 47
  • 8
    The short answer is: they made the terrible design choices long, long ago, before anybody knew any better, and now we're stuck with it being terribly designed forever. – Louis Wasserman Mar 18 '20 at 18:43
  • Does this answer your question? [Why is Cloneable not deprecated?](https://stackoverflow.com/questions/26398951/why-is-cloneable-not-deprecated) – jrook Mar 18 '20 at 18:56
  • because "modifier `native` not allowed" ..in an interface (..and `clone` *is* native...answers Q1-Q4) – xerx593 Mar 18 '20 at 19:00
  • Note: `Object.clone()` does not check whether a `Cloneable` class overrides `clone()` or not. It doesn't care. In practice, you almost always do need to override that method, to (1) make the method public, (2) suppress the useless checked exception that will never be thrown, (3) deep clone any fields. But it's not strictly required to override it and it is not checked. – Boann Mar 18 '20 at 19:39
  • One more doubt why `Object` declares `clone()` as `protected`? Every class is subclass of `Object`, so it will be visible to all classes, right? Is this another bad design decision? – MsA Mar 19 '20 at 19:31
  • If `clone()` were public, it would force every `Cloneable` class to keep that method public, to be publicly cloneable. By making the base method protected, a class can choose whether to be publicly cloneable, or to only allow clones that it creates itself. I've never seen a real use for it, but there is some theoretical logic behind it. – Boann May 09 '20 at 14:57

1 Answers1

6

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.

user
  • 7,435
  • 3
  • 14
  • 44
  • What do you mean by " Object.clone can't really be overridden"? In eclipse, when we try to add `clone()` to our class, eclipse itself adds `@Overrides` to it. – MsA Apr 13 '20 at 07:30
  • @anir I'm sorry, I'll fix my answer. I meant that you can't do the native stuff involved in copying objects yourself. – user Apr 13 '20 at 14:23