Some time ago, I described a couple of surprising design choices in the JDK functional interfaces API.
Lately, during a lesson, a student of mine proposed to shallow-copy an
ArrayList by using the
clone() method: I thought this is another API gotcha worth writing about.
Cloning an object means a new object is created with the same state as the original one.
As per the JavaDoc:
Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object. The general intent is that, for any object
x, the expression:
x.clone() != x
true, and that the expression:
x.clone().getClass() == x.getClass()
true, but these are not absolute requirements. While it is typically the case that:
true, this is not an absolute requirement.
If I were to design
Cloneable from scratch, this is what I would probably end up doing:
This way, only classes implementing
Cloneable have a
clone() method. I believe this is the standard way to use a type system.
With generics, it could even be improved:
Interestingly enough, the design provided by the JDK is quite different:
Compared to the nominal design:
Cloneableinterface has no method defined - it’s a marker interface.
Objectclass provides the
A class implements the
Cloneableinterface 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
Cloneableinterface results in the exception
With that approach, checks are made at runtime instead of compile time. This is not something to expect from a language with static typing!
clone() in a box, lock it, throw away the key and forget it ever existed.
The Java API provides two ways to copy a