19

If I have:

class foo implements Cloneable

and then do:

bar = new foo();
bar.clone();

I get a shallow copy without needing to write any bar.clone() code like I normally would need to do when I implement an interface.

My understanding is that an interface's functions must be filled in by the class implementing it, and Object.clone() has no implementation (as per the docs, "The class Object does not itself implement the interface Cloneable")

So where does my shallow clone come from? Where is the code that implements bar.clone() if Object.clone() has no implementation? I'm confused.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
ambertch
  • 7,581
  • 4
  • 28
  • 40

4 Answers4

29

Be very careful using clone. In fact, I would avoid it completely. I have never needed it. BUT... that being said, the best discussion of the topic I have ever read is by Joshua Bloch, in Effective Java. Read Item 11: "Override clone judiciously".

PLEASE do yourself a favor and read that item. I actually recommend reading that entire chapter (and the rest of the book). Everything you need to know about clone and why I caution you about it is in there.

Hope this helps.

nhaarman
  • 98,571
  • 55
  • 246
  • 278
Tom
  • 21,468
  • 6
  • 39
  • 44
  • 3
    +1 for Effective Java. The discussion on cloning is great, as is the entire book. – Jim Ferrans Jul 01 '09 at 05:57
  • This should almost be the only answer. Given Joshua Bloch's excellent discussion of the design flaws inherent in Cloneable, one could almost say that it's just a design mistake in Java to begin with. You're almost always better off using a copy constructor/static factory. – Visionary Software Solutions Jun 12 '13 at 20:37
7

Object.clone() has an implementation:

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html#clone()

This link explains the Cloneable interface: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Cloneable.html

An object must implement the Cloneable interface in order to call the clone() method, otherwise, it throws a CloneNotSupportedException.

By definition, all classes in Java extend the base Object class, and Object class has a default clone() method, even though Object itself does not implement Cloneable. The Object class's clone() method will be called if you do not override it yourself.

Cambium
  • 19,152
  • 3
  • 26
  • 19
  • ah i see. I misread the docs - object DOES have code for clone(), it just doesn't implement cloneable So then what is the mechanism for enforcing the cloneable implementation in order to call class.clone()? Is this just something JRE is aware of to deliberately check? – ambertch Jul 01 '09 at 05:38
  • The quick answer -- nothing. The interface dtermines the behaviour of Object's clone() implementation. If a class is Cloneable, Object.clone() returns a copy, otherwise it throws CloneNotSupportedException. The Cloneable interface essentially modifies the behaviour of its superclass's implementation of clone(). – Cambium Jul 01 '09 at 05:54
1

If I have: "class foo implements cloneable"

and then do: bar = new foo(); bar.clone();

I get a shallow copy without needing to write any bar.clone() code like I normally would need to do when I implement an interface.

That would only work if you are calling it within the class "foo", because the .clone() method inherited from Object is protected.

My understanding is that an interface's functions must be filled in by the class implementing it, and Object.clone() has no implementation (as per the docs, "The class Object does not itself implement the interface Cloneable")

(1) Object.clone() does have an implementation. It makes a shallow copy of the object if the object implements Cloneable. (2) The .clone() method is not part of any interface. (3) Having a .clone() method and implementing the Cloneable interface are completely separate things. You only need to implement the Cloneable interface if you intend to make use of Object's clone method; however, this is the recommended way to write a clone method for your class -- to get its copy from the superclass's clone method, which eventually goes up to Object's clone method.

newacct
  • 119,665
  • 29
  • 163
  • 224
  • Thanks, yes you're write - my bad as I misread the sentence and conflated "implements coneable" with "having an implementation" – ambertch Jul 02 '09 at 19:04
  • why "**That would only work if you are calling it within the class "foo", because the .clone() method inherited from Object is protected.**" .what if my subclass calls foo.clone()? its absolutely possible right ? – amarnath harish Apr 04 '18 at 08:42
  • @amarnathharish: If you mean class `foo` didn't implement any `clone()` method, and you have a class `subfoo` that extends `foo`, and inside `subfoo` you call `new foo().clone()`, no, that wouldn't work, because `clone()` is declared in a different package, and `subfoo` cannot access a protected member on an expression that's not its own type (e.g. `foo`) when the protected member is declared in a different package – newacct Apr 04 '18 at 17:36
  • i never mentioned `subfoo` is in different package, so i guess it can be accessed from same package without worries – amarnath harish Apr 05 '18 at 12:46
  • @amarnathharish: No, `subfoo` could be in the same package as `foo`, but `Object.clone()` is declared in a different package because `Object` is in a different package – newacct Apr 05 '18 at 15:04
  • `protected` fields and methods can be accessed from different package. i dont understand what you mean – amarnath harish Apr 06 '18 at 04:20
  • @amarnathharish: It's hard to understand your description. But if you are saying that `foo` doesn't implement a `clone` method, and you can make a class `subfoo` that extends `foo` in the same package, and inside `subfoo` you do `new foo().clone()`, that won't compile. Try it, and you will see that it doesn't compile. Even though `new foo().clone()` will compile inside `foo`, it won't compile inside `subfoo`. – newacct Apr 06 '18 at 17:23
  • `package learn; public class foo implements Cloneable { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub } protected foo clone() throws CloneNotSupportedException{ return new foo(); }} class subfoo extends foo implements Cloneable { public static void main(String[] args) { // TODO Auto-generated method stub foo f = new foo(); try { f.clone(); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } ` here i didnt say foo doesnt implement clone – amarnath harish Apr 06 '18 at 17:47
  • @amarnathharish: the question, as I understand it, is about when `foo` doesn't implement `clone()` – newacct Apr 07 '18 at 00:15
1

My understanding is that an interface's functions must be filled in by the class implementing it, and Object.clone() has no implementation (as per the docs, "The class Object does not itself implement the interface Cloneable")

there is a difference between saying Object.clone() has no implementation and The class Object does not itself implement the interface Cloneable

Object's clone method does have implementation, it does memory-copy of the object who called clone method.

you are right, Object class does not implement cloneable, all it does is check the object is cloneable or not .

the above answer point's you to read some book, i think i can give a quick solution so to answer your question

So where does my shallow clone come from? Object's clone method

Where is the code that implements bar.clone() if Object.clone() has no implementation? it has implementation, written in native code.

amarnath harish
  • 945
  • 7
  • 24