122

What is the specific reason that clone() is defined as protected in java.lang.Object?

Paul Bellora
  • 54,340
  • 18
  • 130
  • 181
Alex N.
  • 14,805
  • 10
  • 46
  • 54

11 Answers11

108

The fact that clone is protected is extremely dubious - as is the fact that the clone method is not declared in the Cloneable interface.

It makes the method pretty useless for taking copies of data because you cannot say:

if(a instanceof Cloneable) {
    copy = ((Cloneable) a).clone();
}

I think that the design of Cloneable is now largely regarded as a mistake (citation below). I would normally want to be able to make implementations of an interface Cloneable but not necessarily make the interface Cloneable (similar to the use of Serializable). This cannot be done without reflection:

ISomething i = ...
if (i instanceof Cloneable) {
   //DAMN! I Need to know about ISomethingImpl! Unless...
   copy = (ISomething) i.getClass().getMethod("clone").invoke(i);
}

Citation From Josh Bloch's Effective Java:
"The Cloneable interface was intended as a mixin interface for objects to advertise that they permit cloning. Unfortunately it fails to serve this purpose ... This is a highly atypical use of interfaces and not one to be emulated ... In order for implementing the interface to have any effect on a class, it and all of its superclasses must obey a fairly complex, unenforceable and largely undocumented protocol"

oxbow_lakes
  • 133,303
  • 56
  • 317
  • 449
  • 2
    If the object isn't Cloneable, then Object's clone() will throw CloneNotSupportedException. So you do need be Cloneable if you're going to call super.clone() (resulting in Object.clone() being called). I don't see how an object can be serialized without implementing Serializable. – Steve Kuo Jul 16 '09 at 17:00
  • Sorry - I wasn't implying that. I was merely implying that "good" design is to *not* make an interface extend `Serializable` - it is up to implementations to decide whether to implement `Serializable`. I was extending this to `Cloneable` - it is not something which an interface should extend - but an implementation of an interface is free to be `Cloneable`. The trouble is, if you have a parameter of the interface type, you ask ask it whether it is cloneable; but then you can't actually clone it! – oxbow_lakes Jul 16 '09 at 17:11
  • The word "mistake" appears nowhere in your quote. And one guy's book does not mean that it's "largely regarded". I would argue the following: 1) the "Cloneable" interface is not intended to indicate that a class had a public clone method, or that a class had any public behavior. It is poorly named, because it might mislead people into thinking that. 2) There does not exist an interface in Java that indicates whether a class could be cloned. However, there aren't interfaces for a lot of things that you wish there were. This does not mean it's a "mistake". – newacct Mar 23 '11 at 04:58
  • @oxbow_lakes : The design of clone and Cloneable is not the main concern here, the question is about why 'protected' (as opposed to why not 'public'). Whatever be your answer, that should also explain why 'finalize' is protected and why other methods like 'toString' is 'public' and not 'protected'. – KGhatak Jun 16 '16 at 10:43
  • @newacct "...one guy's book does not mean that it's largely regarded...." It's not just any random guy's book. Joshua Bloch is the creator of the Java language. If he believes that the Cloneable interface is messed up then we can't argue with that. – BOT_bkcd Nov 11 '21 at 07:46
31

The Clonable interface is just a marker saying the class can support clone. The method is protected because you shouldn't call it on object, you can (and should) override it as public.

From Sun:

In class Object, the clone() method is declared protected. If all you do is implement Cloneable, only subclasses and members of the same package will be able to invoke clone() on the object. To enable any class in any package to access the clone() method, you'll have to override it and declare it public, as is done below. (When you override a method, you can make it less private, but not more private. Here, the protected clone() method in Object is being overridden as a public method.)

Bill K
  • 62,186
  • 18
  • 105
  • 157
  • Which is fine, *until you bring interfaces into the mix* - try and attempt to clone an unknown implementation of `Set` – oxbow_lakes Jul 16 '09 at 16:57
  • @oxbow_lakes: but maybe some implementations of Set are not cloneable – newacct Jul 16 '09 at 17:25
  • 3
    You can't clone anything that doesn't implement the Clonable interface--it's a marker that says "This class is properly clonable"--very similar to the Serializable interface. By the way, there is a way to clone classes via serialization that works well--google something like "java serialization clone" and you'll probably find a handful of ways to get a deep copy of your object. – Bill K Jul 16 '09 at 20:00
  • 4
    You can't clone anything that doesn't implement the Cloneable interface, but just because something implements the Cloneable interface doesn't mean you can clone it. – Michael Myers Jul 24 '09 at 22:23
  • @mmyers Your comment is correct, but if that was in reply to the comment above it then you missed what I was saying. A class that can't be cloned but can be serialized can be "cloned" (or let's just say copied) via serialization. This makes an excellent, cheap (to code) cloning system, just serialize it out to a byte array and serialize it back into another variable. – Bill K Jul 27 '09 at 06:51
  • @Bill K : I don't get the override & increase visibility logic here. If I have to settle with this explanation, then would you pls additionally explain, why the same is not applied for rest of the methods (except 'finalize') ? Say, why 'toString' is not protected? – KGhatak Jun 16 '16 at 10:47
  • 1
    @BuckCherry toString has a default implementation, if you call it something good will happen and you will get back a string. equals has a default implementation (same as ==). Clone can't have a default implementation. If you call clone on an object that hasn't implemented it, you will not get reasonable behavior. Cloning is complicated and can't really be done automatically (some objects without default constructors can be impossible to generically clone), so by default they make it a little safer. I think putting it on Object at all, however, might not have been necessary. – Bill K Jun 16 '16 at 16:02
8

clone is protected because it is something that ought to be overridden so that it is specific to the current class. While it would be possible to create a public clone method that would clone any object at all this would not be as good as a method written specifically for the class that needs it.

Andrew Hare
  • 344,730
  • 71
  • 640
  • 635
  • but why has it to be protected for that? – Janusz Jul 16 '09 at 16:31
  • 3
    It's protected so you don't use the one in object (it'll just throw an exception anyway). They want you to override it in a class, then you make it public. (answered a couple times below too) – Bill K Jul 16 '09 at 16:41
  • 1
    And useless when considering interfaces as per my point below – oxbow_lakes Jul 16 '09 at 17:19
  • ought to be overridden is not very clear then it should have been abstract and then must not in Object Class, I am trying hard to understand why is it so. – Kumar Abhishek Jan 06 '17 at 18:08
4

The Clone method can't be directly used on any object, which is why it is intended to be overriden by the subclass.

Of course it could be public and just throw an appropriate exception when cloning is not possible, but i think that would be misleading.

The way clone is implemented right now makes you think about why you want to use clone, and how you want your object to be cloned.

Silfverstrom
  • 28,292
  • 6
  • 45
  • 57
3

It is protected because the default implementation does a shallow memberwise copy of all fields (including private), circumventing constructor. This is not something an object might be designed to handle in the first place (for example, it might keep track of created object instances in a shared list, or something similar).

For the same reason, the default implementation of clone() will throw if the object it's called on doesn't implement Cloneable. It's a potentially unsafe operation with far-reaching consequences, and therefore author of the class must explicitly opt-in.

Carl Manaster
  • 39,912
  • 17
  • 102
  • 155
Pavel Minaev
  • 99,783
  • 25
  • 219
  • 289
  • Actually the default implementation (in object) throws an exception according to the docs... – Bill K Jul 16 '09 at 16:40
  • 2
    No, it doesn't just throw. From its JavaDoc: "The method clone for class Object performs a specific cloning operation. First, if the class of this object does not implement the interface Cloneable, then a CloneNotSupportedException is thrown. Note that all arrays are considered to implement the interface Cloneable. Otherwise, this method creates a new instance of the class of this object and initializes all its fields with exactly the contents of the corresponding fields of this object, as if by assignment; the contents of the fields are not themselves cloned." – Pavel Minaev Jul 16 '09 at 16:55
3

IMHO it's as simple as this:

  • #clone must not be called on non-cloneable objects, therefore it is not made public
  • #clone has to be called by subclasses ob Object that implement Cloneable to get the shallow copy of the right class

What's the right scope for methods that shall be callable by subclasses, but not by other classes?

It's protected.

Classes implementing Cloneable of course will make this method public so it can be called from other classes.

Michaela Elschner
  • 1,268
  • 1
  • 10
  • 22
2

From the javadoc of cloneable.

* By convention, classes that implement this interface (cloneable) should override 
* <tt>Object.clone</tt> (which is protected) with a public method.
* See {@link java.lang.Object#clone()} for details on overriding this
* method.

* Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
* Therefore, it is not possible to clone an object merely by virtue of the
* fact that it implements this interface.  Even if the clone method is invoked
* reflectively, there is no guarantee that it will succeed.

So you could call clone on every object but this would give you most of the time not the results you want or an exception. But is only encouraged if you implement cloneable.

Janusz
  • 187,060
  • 113
  • 301
  • 369
0

Clone() method has a check internally 'instance of Cloneable or not'.This is how Java team might thought will restrict the improper use of clone() method.clone() method is protected i.e. accessed by subclasses only. Since object is the parent class of all sub classes, so Clone() method can be used by all classes infact if we don't have above check of 'instance of Cloneable'. This is the reason Java team might have thought to restrict the improper use of clone() by having the check in the clone() method 'is it instance of Cloneable'.

Hence whatever classes implement cloneable can use clone() method of Object class.

Also since it made protected, it is available to only those sub classes that implements cloneable interface. If we want to make it public, this method has to be overridden by the sub class with their own implementation of it.

SARIKA
  • 29
  • 2
-1

Yes, same problem that I met. But I solve it by implementing this code

public class Side implements Cloneable {
    public Side clone() {

        Side side = null;
        try {
            side = (Side) super.clone();
        } catch (CloneNotSupportedException e) {
            System.err.println(e);
        }
        return side;
    }
}

Just as the before someone said.

  • 2
    CloneNotSupportedException is another example of a checked exception that should be unchecked (that is, it should extend RuntimeException, not Exception). Though method clone() in class Side implements Cloneable and therefore will never throw CloneNotSupportedException, Side.clone() must still catch or declare the exception. This just adds superfluous exception handling noise to the clone() method. – Derek Mahar Nov 11 '09 at 18:41
-2

Well, also the sun developers are only human, and they did indeed make huge mistake to implement the clone method as protected, the same mistake as they implemented a non-functioning clone method in ArrayList! So, in general, there exist a much deeper misunderstanding of even experienced Java programmers about the clone method.

However, I've recently found a fast and easy solution to copy any object with all its content, no matter how it is built and what it contains, see my answer here: Bug in using Object.clone()

Community
  • 1
  • 1
mark
  • 84
  • 1
  • 2
-4

Again, Java JDK framework shows brilliant thinking:

Cloneable interface does not contain a "public T clone();" method because it acts more like an attribute (eg. Serializable) which allows an instance it to be cloned.

There is nothing wrong with this design because:

  1. Object.clone() will not do what you want with your custom-defined class.

  2. If you have Myclass implements Cloneable => you overwrite clone() with "public MyClass clone()"

  3. If you have MyInterface extends Cloneable and some MyClasses implementing MyInterface: simply define "public MyInterface clone();" in the interface and every method using MyInterface objects will be able to clone them, no matter their MyClass-class.

Fabian Schmengler
  • 24,155
  • 9
  • 79
  • 111
Victor
  • 1
  • 2
    if your class happen to be inherited your derived class clone implementation wont be safe till your base class implementations provide safe clone methods. Also, it is kind of unusual design condition to have an interface without method/attribute. This interface does not force class to implement clone. – prap19 Oct 25 '11 at 13:48