15

I know that clone() is a protected method, but "protected" means that it is accessible for all subclasses of particular class.

Any Java class is a subclass of Object, so what is the reason for the protected method here?

And why can we call clone() only on classes that implement the Cloneable interface? I can't understand how it connects to the fact that clone() in Object is declared as protected.

arshajii
  • 127,459
  • 24
  • 238
  • 287
Don_Quijote
  • 936
  • 3
  • 18
  • 27
  • 7
    it's a sad story.. :) cloning in java doesn't work properly (well, it does, but after a lot of effort), so avoid it. – Bozho Aug 14 '13 at 19:03
  • 3
    `Cloneable` is actually a pretty broken interface, and shouldn't be considered as a good example. It works mostly by magic, honestly. – Louis Wasserman Aug 14 '13 at 19:03
  • 1
    Read: http://stackoverflow.com/q/2156120/203907 – Bozho Aug 14 '13 at 19:06
  • 3
    Read Josh Bloch's Effective Java to see why Cloneable and clone() are broken. Use a copy constructor or similar solution instead. – rob Aug 14 '13 at 19:07

6 Answers6

12

Object's clone() method is quite special, as it always returns an instance of the current class that has all fields copied (even final). I don't think its possible to reproduce this with plain Java code, not even with reflection.

Because of this, it must be made available to all classes, but since it should not be callable from the outside by default because you don't want everything to be cloneable, it must be protected.

As an additional check, clone checks that the class implements Cloneable, only to ensure you don't clone non-cloneables by accident.


All in all, cloning is somewhat broken because it doesn't work when you need to deep-copy final fields. I recommend you implement instance copying manually, following this pattern.

public class Base {

    /** one or more public constructors */
    public Base() { ... }

    /** copy-constructor */
    protected Base(Base src) { /* copy or deep-copy the state */ }

    public Base copy() { return new Base(this); }
}

public class Derived extends Base {

    /** one or more public constructors */
    public Derived() { ... }

    /** copy-constructor */
    protected Derived(Derived src) { 
        super(src);
        /* copy or deep-copy the state */ 
    }

    @Override
    public Derived copy() { return new Derived(this); }
}
Cephalopod
  • 14,632
  • 7
  • 51
  • 70
6

Because that's the way they designed it. There's a statement somewhere in the Bug Parade that the original reasons for the design are 'lost in the mists of time', but I remember a discussion by Sun in the 1990s that said the design gave four possible behaviors.

Cannot remember the details :-| But you can work it out:

  1. Do nothing. Class cannot be cloned and clone() method is inaccessible except to derived classes.
  2. Implement Cloneable: Class can be cloned but clone() method is inaccessible except to derived classes.
  3. Implement Cloneable and provide your own clone() method: as (2) but the possibility exists to make clone() public and also now to return the correct type.
  4. Derived from a class that does (2) or (3), implement clone(), and throw NotCloneableException: you are back to 1.

Putting clone() into the interface would have lost some of that.

user207421
  • 305,947
  • 44
  • 307
  • 483
3

The default implementation of Object.clone() is the only way (other than perhaps Reflection) via which a base-type method in an object can produce a new object of that object's same type. On the other hand, there are many classes for which it would be impossible for a derived class to implement a working clone method which would not violate the base-class invariants. It was desired that such derived classes not be allowed to call clone and receive an object that couldn't possibly be usable.

In retrospect, the proper thing to have done might have been to define a system CloneableObject which inherits from Object which includes a protected memberwiseclone method (that works like Object.clone() does now) and nothing else, and have all classes which are going to be cloneable inherit from that as their base type. That type could use then some special magic within its clone() method that was unavailable to other types. Instead, however, the system uses the existence of the Cloneable interface to decide whether objects should be allowed to use the base-level clone() method. Not a great design, but it is what it is. Hard to say whether that's better or worse than the .NET approach of allowing nearly all derived classes to call MemberwiseClone whether or not there would be any way a derived class could do so without yielding a broken object.

supercat
  • 77,689
  • 9
  • 166
  • 211
2

Cloneable is an interface and in order to clone a reference to an abstract base class, either the base class must have a clone() method, or one of its parents must have a publicly accessible clone() method. Cloneable just acts as a marker interface.

Please refer to:

Community
  • 1
  • 1
Ankit Zalani
  • 3,068
  • 5
  • 27
  • 47
  • But how does Cloneable interface connected to the fact that clone method is protected? – Don_Quijote Aug 14 '13 at 19:09
  • 1
    Please refer the link for it's answer: http://stackoverflow.com/questions/1138769/why-is-the-clone-method-protected-in-java-lang-object – Ankit Zalani Aug 14 '13 at 19:10
  • 1
    I will repeat myself: I know that clone() is a protected method, but "protected" means that it is accessible for all subclasses of particular class. Any Java class is a subclass of Object, so what is the reason for the protected method here? And in common - what is the reason to have protected methods in Object? – Don_Quijote Aug 14 '13 at 19:17
  • 1
    @Don_Quijote it means that you can override it in your class if you want **but** it can't be accessed directly since it's not `public`. If you check the duplicated question you will have a better understanding. – Luiggi Mendoza Aug 14 '13 at 19:19
  • @Don_Quijote: `protected` means it's accessible to code in the same class, but not to code outside the class. That's the reason to have protected methods in `Object` -- so that classes can use the method internally, but outside code cannot invoke that method on it. And the `Cloneable` interface has nothing at all to do with the fact `Object.clone()` is protected. The `Cloneable` interface simply affects whether `Object.clone()` will throw an exception or not. – newacct Aug 15 '13 at 09:01
1

http://docs.oracle.com/javase/7/docs/api/java/lang/Cloneable.html

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.

By convention, classes that implement this interface should override Object.clone (which is protected) with a public method. See Object.clone() for details on overriding this method.

Note that this interface does not contain the clone 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.

Coming to your question even though Object has protected method clone Object does not implement Cloneable,But the object being called the clone() method must implement Cloneable interface.

Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
  • 1
    OK, but why cone method is protected? – Don_Quijote Aug 14 '13 at 19:11
  • [The exact question on the same site](http://stackoverflow.com/questions/1138769/why-is-the-clone-method-protected-in-java-lang-object),Please prefer to read. – Suresh Atta Aug 14 '13 at 19:17
  • 1
    -1: you appear to be quoting the API docs, but the words you've put in quote tags are not found anywhere on that page. And they're incorrect. – kdgregory Aug 15 '13 at 11:38
  • @kdgregory Thanks for the concern kd,I added all the lines from docs,Previously I added the First point only,Please check. – Suresh Atta Aug 15 '13 at 11:41
-1

Cloneable is a marker interface. The clone() method isn't defined by the Cloneable interface.

The clone method in the Object class is protected to prevent a client class from calling it - Only subclasses can call or override clone, and doing so is a bad idea.

Bill Horvath
  • 1,336
  • 9
  • 24