Why is Cloneable not deprecated?

Kao picture Kao · Oct 16, 2014 · Viewed 9.1k times · Source

It is commonly understood that Cloneable interface in Java is broken. There are many reasons for this, which I will not mention; others already did it. It is also the position of Java architects themselves.

My question is therefore: why has is not been deprecated yet? If the core Java team have decided that it is broken, then they must also have considered deprecation. What are their reasons against doing so (in Java 8 it is still not deprecated)?

Answer

Kao picture Kao · Oct 16, 2014

There is a bug submitted in 1997 to Java Bug Database about adding clone() method to Cloneable, so it would no longer be useless. It was closed with resolution "won't fix" and justification was as follows:

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.

So, although this is not directly about deprecated, the reason for not making Cloneable "deprecated" is that Technical Review Comitee decided that modifying existing documentation will be sufficient enough to make this interface useful. And so they did. Until Java 1.4, Cloneable was documented as follows:

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.

Attempts to clone instances that do not implement the Cloneable interface result in the exception CloneNotSupportedException being thrown.

The interface Cloneable declares no methods.

Since Java 1.4 (which was released in February 2002) up to current edition (Java 8) it looks like this:

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.