Effective Java: Analysis of the clone() method

Geek picture Geek · Jul 18, 2012 · Viewed 8.3k times · Source

Consider the following from Effective Java Item 11 (Override clone judiciously) where Josh Bloch is explaining what is wrong with the clone() contract .

There are a number of problems with this contract. The provision that “no constructors are called” is too strong. A well-behaved clone method can call constructors to create objects internal to the clone under construction. If the class is final, clone can even return an object created by a constructor.

Can someone explain what Josh Bloch is saying in the first paragraph by "If the class is final, clone can even return an object created by a constructor." What does final have to do with clone() here?

Answer

Matt picture Matt · Jul 18, 2012

It's because typical implementations of clone() look like this:

public class MyClass implements Cloneable {
  protected Object clone() {
    MyClass cloned = (MyClass) super.clone();
    // set additional clone properties here
  }
}

In this way you can inherit the cloning behavior from your superclass. It's widely assumed that the result of a clone() operation will return the correct instance type based on the object it was called on. Ie. this.getClass()

So if a class is final, you don't have to worry about a subclass calling super.clone() and not getting the right object type back.

public class A implements Cloneable {
    public Object clone() {
       return new A();
    }
}


public class B extends A {
    public Object clone() {
       B b = (B)super.clone(); // <== will throw ClassCastException
    }
}

But, if A is final, no one can extend it, and thus it's safe to use a constructor.