JDK-4098033 : Cloneable doesn't define .clone
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 1.1.4,1.1.5,1.2.0,1.3.0,5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS:
    generic,solaris_2.5.1,solaris_2.6,windows_nt,windows_xp generic,solaris_2.5.1,solaris_2.6,windows_nt,windows_xp
  • CPU: generic,x86,sparc
  • Submitted: 1997-12-09
  • Updated: 2014-10-25
  • Resolved: 2000-07-15
Related Reports
Duplicate :  
Name: mf23781			Date: 12/09/97

Cloneable doesn't define clone.  This means that programmers cannot
polymorphically clone objects, such as in:

    for (int i = 0; i < myVector.size(); i++) {
            ((Cloneable) myVector.elementAt()).clone(), i);

Secondly, programmers have no idea whether clones are deep or shallow.

Since interfaces cannot be changed, suggested solution:
     add an interface for deep clones:

    public interface interface Copyable {
       public Object clone(); // guarantees deep clone
###@###.### 11/3/04 21:17 GMT

In response to the TRC recommendation quoted above, particularly the phrase "lost in the mists of time", Frank Yellin wrote the following email message on a Sun-internal mailing list. At this point I doubt confidentiality is an issue, since the message is 14 years old, and it contains useful and interesting history and rationale. ========== From: Frank Yellin Date: 2000-06-21 Subject: Cloneable: The alte kakker speaks Losts in the mists of time? I'm not that old, yet. Here is, to the best of my recollection, the reasons for the way things are. Cloneable has no methods for the same reason that Serializable doesn't. [Actually, the statement should be the other way around, since Cloneable came first.] Cloneable indicates a property of the class, rather than specifically saying anything about the methods that the class supported. You may say that this is an abuse of the "purpose" of interfaces. It certainly isn't any worse than the common custom of definining an interface with nothing but lots of constants in it, and then having classes "implement" that interface in order to able to use the constants without a class modifier. Prior to reflection, we needed a native method to make a shallow copy of an Object. Hence Object.clone() was born. It was also clear that many classes would want to override this method, and that not every class would want to be cloned. Hence Cloneable was born to indicate the programmer's intention. So, in short. The purpose of Cloneable was not to indicate that you had a public clone() method. It was to indicate that you were willing to be cloned using Object.clone(), and it was up to the implementation to decide whether or not to make clone() public. ==========

WORK AROUND Name: mf23781 Date: 12/09/97 ====================================================================== Name: tb29552 Date: 03/12/2000 Get the Class object, examine the interfaces it implements to see if it implements Cloneable(), if so do a dynamic method call on the clone() method.... (Review ID: 102333) ====================================================================== ken.arnold@East 2000-03-13 Oh, yes, this is certainly possible. It is *really*, ugly. So it should be documented as a workaround, but it should not deter us from fixing the problem. This is in the "workaround as painful as needles under your fingernails" realm.


EVALUATION Cloneable doesn't define a public clone() operation, making it practically useless. For obvious reasons, we'll never be able to add a public clone operation to Cloneable, but we will be able to make a new interface that extends Cloneable and does what Cloneable should have done. What to call this new interface is open to debate (Clonable? Copyable? Herbert?) At any rate, I believe that this should definitely be implemented in the next major release after 1.2. joshua.bloch@Eng 1998-04-28 ======================================================================== You know, I just thought of something. The "obvious" reason we can't add clone() to Cloneable is that adding new methods to interfaces is an incompatible change. The reason adding new methods is incompatible is that is makes concrete classes suddenly abstract. But in this case that wouldn't happen -- existing classes *all* have a clone method. No such class would be abstract. This may be an exception to the incompatible change-ness of adding methods to interfaces. We at least ought to consider this, because if we *can* add it to Cloneable it fixes a problem with existing systems, whereas if we add a new interface we only fix new code written by highly-informed people. The downside I see is that we will public-ify the clone method of any existing class that both implements Cloneable but doesn't declare clone as public. I have always found it hard to imagine the value of such a thing, and so I doubt this is a serious issue in deep principle. But others may disagree. In any case, this is clearly the ideal fix, and our instincts that it isn't possible are probably wrong. ken.arnold@East 2000-02-28: Unfortunately, this does not work; the clone method in Object is protected, not public. All methods in interfaces are inherently public. Thus, a class that currently implements Cloneable but has no public clone method would break. In practice, I doubt that there are many such classes out there, but there are almost certainly a few. It is worth noting that adding methods to interfaces breaks source compatibility, and not binary compatibility. In this instance, we might consider intentionally breaking source compatibility, knowing that the odds of a problem are low. joshua.bloch@Eng 2000-02-28 Ah, yes, if I inherit a public method from an interface that is satisified by an inherited method of the same signature from my superclass, but with more restricted access, I must redeclare the more restricted access method that statisfies it as public -- it is not made public by inference. I had forgotten that point, and so assumed that the protected method would be made public by virtue of inheriting a public method of the same signature. Sigh, at least in this case. It could have solved it so much nicer. ken.arnold@East 2000-02-29 Sun's Technical Review Committee (TRC) considered this issue at length and recommended against taking any action other than improving the documentation of the current Cloneable interface. Here is the full text of the recommendation: The existing Java object cloning APIs are problematic. There is a protected "clone" method on java.lang.Object and there is an interface java.lang.Cloneable. The intention is that if a class wants to allow other people to clone it, then it should support the Cloneable interface and override the default protected clone method with a public clone method. Unfortunately, for reasons conveniently lost in the mists of time, the Cloneable interface does not define a clone method. This combination results in a fair amount of confusion. Some classes claim to support Cloneable, but accidentally forget to support the clone method. Developers are confused about how Cloneable is supposed to work and what clone is supposed to do. Unfortunately, adding a "clone" method to Cloneable would be an incompatible change. It won't break binary compatibility, but it will break source compatibility. Anecdotal evidence suggests that in practice there are a number of cases where classes support the Cloneable interface but fail to provide a public clone method. After discussion, TRC unanimously recommended that we should NOT modify the existing Cloneable interface, because of the compatibility impact. An alternative proposal was to add a new interface java.lang.PubliclyCloneable to reflect the original intended purpose of Cloneable. By a 5 to 2 majority, TRC recommended against this. The main concern was that this would add yet more confusion (including spelling confusion!) to an already confused picture. TRC unanimously recommended that we should add additional documentation to the existing Cloneable interface to better describe how it is intended to be used and to describe "best practices" for implementors. joshua.bloch@Eng 2000-07-14 A new SR opened for this report suggests that only classes failing to support the contract of Cloneable would encounter a source incompatibility. This is incorrect. A Cloneable class with a protected (not public) clone method would be faithfully honoring its contract, but would no longer compile. . ###@###.### 11/3/04 21:42 GMT