Confusion about cloneable interface and object.clone() in java
Asked Answered
V

4

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.

Venn answered 1/7, 2009 at 5:17 Comment(0)
E
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.

Epanorthosis answered 1/7, 2009 at 5:39 Comment(2)
+1 for Effective Java. The discussion on cloning is great, as is the entire book.Baryram
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.Tova
E
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.

Express answered 1/7, 2009 at 5:20 Comment(2)
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?Venn
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().Express
J
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.

Johnsonjohnsonese answered 1/7, 2009 at 9:44 Comment(9)
Thanks, yes you're write - my bad as I misread the sentence and conflated "implements coneable" with "having an implementation"Venn
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 ?Heeley
@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 packageJohnsonjohnsonese
i never mentioned subfoo is in different package, so i guess it can be accessed from same package without worriesHeeley
@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 packageJohnsonjohnsonese
protected fields and methods can be accessed from different package. i dont understand what you meanHeeley
@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.Johnsonjohnsonese
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 cloneHeeley
@amarnathharish: the question, as I understand it, is about when foo doesn't implement clone()Johnsonjohnsonese
H
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.

Heeley answered 4/4, 2018 at 8:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.