Checker Clone   as of Julia version 2.4 (built on 23 Oct 2017)

belongs to group Basic

Identify possibly incorrect object cloning implementations


This checker identifies frequent problems in the definition of the method clone(). That method is used to generate a clone of an object, that is, a distinct instance with the same behavior as the original one. The default implementation in java.lang.Object checks that the object to clone implements the interface java.lang.Cloneable or otherwise throws a java.lang.CloneNotSupportedException. Hence, in order to clone an object it is in general enough to implement that interface and use the default implementation of clone(). It is also possible to override that default implementation. Note that a class that inherits the default implementation allows its subclasses to implement java.lang.Cloneable and clone its instances.

Action: Check that clone() is only redefined in classes that implement java.lang.Cloneable. Check that the default implementation of clone() is only used for classes that have explicitly declared to implement java.lang.Cloneable.

Examples


Consider the following classes:

public class TestClone1 {

  @Override
  public Object clone() {
    return new TestClone1();
  }
}

and

public class TestClone2 {
  private int data;
  private String s;

  public TestClone2(int data, String s) {
    this.data = data;
    this.s = s;
  }
}

This checker issues the following warning:

TestClone1.java:5: [Clone: CloneForNonCloneableWarning] Method clone() is defined here, but class TestClone1 does not implement java.lang.Cloneable

since it is unexpected to override the clone() method without implementing the java.lang.Cloneable interface.

If the allowsCloningByExtension option is set to false (its default is true), then this checker will also issue the following warning:

TestClone2.java:1: [Clone: SubclassesMayBeClonedWarning] Non-cloneable class TestClone2 allows one to define cloneable subclasses

since subclasses might exploit the default clone() method to get a complete dump of the private data of the class instances, as in the following example:

public class CloneableTestClone2 extends TestClone2 implements Cloneable {
  public CloneableTestClone2(int data, String s) {
    super(data, s);
  }
}

In this case, it is enough to define class TestClone2 as final, so that the previous exploit cannot be accomplished and Julia will not issue the second warning.