I was reading up on performing a deep-copy of an array correctly, however I was confused about how the #clone() is implemented. It is a member of the java.lang.Object class, and yet if you read the javadocs:
First, if the class of this object does not implement the interface Cloneable, then a CloneNotSupportedException is thrown.
So why define the clone method there in the first place? Surely if a method can only be used when an interface is present, you’d put the method in the interface. The Cloneable interface itself is empty; it is just a marker interface used by Java to ensure that using the clone method is legal.
Doing it this way also removes the ability to make use of generics to ensure type safety:
class Foo implements Cloneable { // Valid.
@Override
public Object clone() throws CloneNotSupportedException {
// ...
}
}
class TypeSafeFoo implements Cloneable<TypeSafeFoo> { // Not valid.
@Override
public TypeSafeFoo clone() throws CloneNotSupportedException {
// ...
}
}
Why has Java done it this way? I’m sure they have legitimate reasons, but I can’t seem to figure it out.
The cloning contract in Java dictates that each
cloneimplementation must first obtain the cloned instance fromsuper.clone(). This creates a chain that always ends with the call toObject.clone, and that method contains "magical" native-level code that makes a binary copy of the underlying rawstructwhich represents the Java object. If this mechanism didn’t exist,clonewould fail to be polymorphic: theObject.clonemethod produces an instance of whatever class it is called on; this cannot be reproduced without native code.This is why the
Object.clonemethod could not have been avoided.Cloneablecould have contained aclonemethod, but it would create issues regarding thethrowsclause. The way it stands, you are free to declareclonewith no declared exceptions, or to declare arbitrary exceptions. This flexibility would not be possible if the method was already declared in the interface.Bear in mind that Generics would be of little use for cloning: imagine
protected T clone()inObject: where wouldTcome from? Would we needObject<T>and force every class to be parameterized on itself, all just to make this semi-deprecated mechanism work a tiny bit better? Keep also in mind that this code is perfectly legal:You can call it: