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?
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 .
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.
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.
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'.
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.
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.
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.
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).
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With