Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Effective Java: Analysis of the clone() method

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?

like image 485
Geek Avatar asked Jul 18 '12 11:07

Geek


People also ask

What does clone () do in java?

The class Object 's clone() method creates and returns a copy of the object, with the same class and with all the fields having the same values. However, Object. clone() throws a CloneNotSupportedException unless the object is an instance of a class that implements the marker interface Cloneable .

Does clone () make a deep copy?

clone() is indeed a shallow copy. However, it's designed to throw a CloneNotSupportedException unless your object implements Cloneable . And when you implement Cloneable , you should override clone() to make it do a deep copy, by calling clone() on all fields that are themselves cloneable.

What is the advantage of cloning in java?

Java keeps references of objects. If two reference are pointing to same object then modification to one reference will reflect in another reference as well. To prevent such situation, cloning is required.

Why is the clone () method protected in java Lang object?

clone() method is protected i.e. accessed by subclasses only. Since object is the parent class of all sub classes, so Clone() method can be used by all classes infact if we don't have above check of 'instance of Cloneable'.


5 Answers

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.

like image 79
Matt Avatar answered Oct 19 '22 20:10

Matt


If a class is not final, clone has to return the most derived class for which it was called. That can't work with a constructor, because clone doesn't know which one to call. If a class is final, it can't have any subclasses, so there's no danger in calling its constructor when cloning.

like image 42
Jordão Avatar answered Oct 19 '22 18:10

Jordão


A class doesn't have to provide its own implementation of clone in order to be cloneable. It can delegate that to its cloneable superclass. Here comes the catch: clone must always return an instance of the same class as the instance it is called on. That is impossible to achieve in the described case if an explicit constructor is called. If the class overridng clone is final, on the other hand, this would be fine.

like image 39
Marko Topolnik Avatar answered Oct 19 '22 19:10

Marko Topolnik


The contract for clone specifies that "By convention, the returned object should be obtained by calling super.clone". If your class is not final and you return something obtained with a constructor invocation, calling super.clone() from a subclass will not return the expected result (first of all, the type of the returned object will not be the type of the subclass, as the native clone() method would return).

like image 20
Costi Ciudatu Avatar answered Oct 19 '22 20:10

Costi Ciudatu


See Jorado answer. This is the explanation. In additional clone has problem in final fields see : http://en.wikipedia.org/wiki/Clone_%28Java_method%29#clone.28.29_and_final_fields

You also should read Josh interview on clone in: http://www.artima.com/intv/bloch13.html

like image 2
Avihai Marchiano Avatar answered Oct 19 '22 18:10

Avihai Marchiano