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 } }