Cloneable is the marker Interface that indicates that clone() may be called on an object. Overriding
clone() without implementing Cloneable can be useful if you want to control how subclasses clone themselves, but otherwise,
it's probably a mistake.
The usual convention for Object.clone() according to Oracle's Javadoc is:
x.clone() != x x.clone().getClass() == x.getClass() x.clone().equals\(x\) Obtaining the object that will be returned by calling super.clone() helps to satisfy those invariants:
super.clone() returns a new object instance super.clone() returns an object of the same type as the one clone() was called on Object.clone() performs a shallow copy of the object's state
class BaseClass { // Noncompliant; should implement Cloneable
@Override
public Object clone() throws CloneNotSupportedException { // Noncompliant; should return the super.clone() instance
return new BaseClass();
}
}
class DerivedClass extends BaseClass implements Cloneable {
/* Does not override clone() */
public void sayHello() {
System.out.println("Hello, world!");
}
}
class Application {
public static void main(String[] args) throws Exception {
DerivedClass instance = new DerivedClass();
((DerivedClass) instance.clone()).sayHello(); // Throws a ClassCastException because invariant #2 is violated
}
}
class BaseClass implements Cloneable {
@Override
public Object clone() throws CloneNotSupportedException { // Compliant
return super.clone();
}
}
class DerivedClass extends BaseClass implements Cloneable {
/* Does not override clone() */
public void sayHello() {
System.out.println("Hello, world!");
}
}
class Application {
public static void main(String[] args) throws Exception {
DerivedClass instance = new DerivedClass();
((DerivedClass) instance.clone()).sayHello(); // Displays "Hello, world!" as expected. Invariant #2 is satisfied
}
}