Misnomer: Cloneable

In my category for Java Misnomers I really should write about this silly interface. 

Not so cloneable

There is an interface Cloneable. But it is empty. Such interfaces are marker interfaces because an empty interface can only be used to mark other types. This concept is from a time before Java Annotations. The problem here is that marking something as cloneable doesn’t make it cloneable.

Shallow Copy

A “clone” is just a shallow copy. The JVM just copies each value but doesn’t invoke the constructor. Sometimes the clone isn’t even a valid object, especially if there is a factory that should create the objects.
The method name clone causes quite some confusion as it isn’t clear what kind of clone it creates. There is no method for a deep copy. And there is no standard way to clone an array or collection of cloneable objects. So what’s the point of the interface?

Alternatives

Define a copy constructor or a static method to clone an object. Books about design patterns should have a chapter about the “Prototype Pattern”. Or just make the type immutable and then you never need to clone any instances.

You could also use libraries that clone objects using serialization or reflection. Those are often a bit slower than specific code but they allow shallow and deep copies and you write and maintain less code.

How it could have been

The class Object already has a clone method:

protected native Object clone() throws CloneNotSupportedException;

It is protected. Any subtype can make it public. But Cloneable doesn’t do that.
The javadoc of Cloneable even states:

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

So why didn’t they declare that in the interface:

public Object clone();

They also didn’t have Generics back then. So they could not have an interface that knows the actual type. clone() always returns Object unless you override it in your class.
Even with Generics you have a problem. What if the class isn’t final and you want to extend it. Then clone() on a subtype should return an instance of that subtype. But you can’t just implement Cloneable again.

Example Code

The extended interface:

public interface Cloneable<T extends Cloneable<T>> {
  public T clone();
}

How it could be used:

public final class SomeClass implements Cloneable<SomeClass> {
  @Override
  public SomeClass clone() {
    try {
      return (SomeClass) super.clone();
    } catch (CloneNotSupportedException e) {
      throw new RuntimeException(e);
    }
  }

  public static void main(String[] args) throws Throwable {
    Cloneable<?>[] arr = new SomeClass[3];
    for (int i = 0; i < arr.length; i++)
      arr[i] = new SomeClass();

    Cloneable<?>[] clones = new SomeClass[arr.length];

    for (int i = 0; i < arr.length; i++)
      clones[i] = arr[i].clone();
    // ...
  }

}

Advanced example: http://pastebin.com/tzeWdvEM

More Problems

There are actually more problems. Does a deep copy enforce immutable types, such as Strings,  to be copied? What about singletons? What about referenced objects that do not implement Cloneable?  Such problems could be addressed by providing a parameter that defines a strategy. This strategy would define how to handle different types of objects. It would also solve the problem of shallow vs. deep copy, because a strategy defines that too. It could even use reflection to clone those that do not implement clone.

Leave a Reply

Your email address will not be published.