The usual convention for Object.clone()
according to Oracle's Javadoc is that:
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 instancesuper.clone()
returns an object of the same type as the one clone()
was called onObject.clone()
performs a shallow copy of the object's stateFor example, the following code:
class BaseClass implements Cloneable { @Override public Object clone() throws CloneNotSupportedException { // Non-Compliant - 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 } }
should be refactored into:
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 } }