clone (Java method)
From Wikipedia, the free encyclopedia
clone() is a method in the Java programming language for object duplication.
Because objects in Java are manipulated through reference variables, there is no direct way to copy an object (We would be trying to duplicate the reference variable rather than the object we control through that variable).
Classes that want copying functionality must implement some method to do so, which is by convention called "clone()". This method usually, in turn, calls the clone() method of its superclass to obtain the copy, until it eventually reaches Object's clone() method. The special clone() method in the base class Object provides a standard mechanism for duplicating objects.
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, clone() throws a CloneNotSupportedException unless the class you are trying to use it on implements the marker interface Cloneable.
The default implementation of Object.clone() performs a shallow copy. When a class desires a deep copy or some other custom behavior, they must perform that in their own clone() method after they obtain the copy from the superclass..
The syntax for calling clone in Java is:
Object copy = obj.clone();
or commonly
MyClass copy = (MyClass) obj.clone();
which provides the typecasting needed to assign the generic Object reference returned from clone to a reference to a MyClass object.
One disadvantage with the design of the clone() method is that the return type of clone() is Object, and needs to be explicitly cast back into the appropriate type (technically a custom clone() method could return another type of object; but that is generally inadvisable).
Another disadvantage is that one often cannot access the clone() method on an abstract type. Most interfaces and abstract classes in Java do not specify a public clone() method. As a result, often the only way to use the clone() method is if you know the actual class of an object; which is contrary to the abstraction principle of using the most generic type possible. For example, if one has a List reference in Java, one cannot invoke clone() on that reference because List specifies no public clone() method. Actual implementations of List like ArrayList and LinkedList all generally have clone() methods themselves, but it is inconvenient and bad abstraction to carry around the actual class type of an object.
[edit] clone() and the Singleton pattern
When writing a class using the Singleton pattern, only 1 instance of that class can exist at a time. As a result, the class must not be allowed to make a clone. To prevent this, override the clone() method using the following code:
public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); }
(Note: This is only necessary if a superclass implements a public clone() method, or to prevent a subclass from using this class's clone() method to obtain a copy. Since classes don't usually inherit a public clone() method (Object doesn't have a public clone() method), it is usually unnecessary to explicitly implement a non-functional clone() method.
[edit] clone() and class hierarchy
When working with the clone() in a hierarchy of classes, there are several things that must be handled properly.
1) Every type reference that needs to call the clone function must have a clone() method in its own class or a publicly accessible clone() method in its parent classes. That means that if you want to clone a reference to an abstract base class, either the base class must have a clone() method, or one of its parents must have a publicly accessible clone() method.
Example
- since varY1 is of type Y, then Y must have clone(), or a parent of Y must have clone()
abstract public class X implements Cloneable { public Object clone() throws CloneNotSupportedException { return super.clone(); } } abstract public class Y extends X { } public class Z extends Y { } public class test1 { public void function() throws CloneNotSupportedException { Y varY1 = new Z(); Y varY2 = (Y) varY1.clone(); } }
2) Every class that has any data other than primitives that has to be cloned must contain a clone() function that handles it. This includes all objects and primitives that are allocated with the new coomand such as variable length arrays. iThis assumes that the programmer wants objects to be cloned, and not just have their reference copied.
Example
- since class Z has a reference to another class, there needs to be specific code to clone that reference.
abstract public class X implements Cloneable { public Object clone() throws CloneNotSupportedException { return super.clone(); } } abstract public class Y extends X { } public class ObjectABC implements Cloneable { public Object clone() throws CloneNotSupportedException { return super.clone(); } } public class Z extends Y { private ObjectABC someABC; public Object clone() throws CloneNotSupportedException { Z newZ = (Z) super.clone(); newZ.someABC = (ObjectABC) someABC.clone(); return newZ; } } public class test1 { public void function() throws CloneNotSupportedException { Y varY1 = new Z(); Y varY2 = (Y) varY1.clone(); } }
Easy Solution
The easiest solution to this is to make the base class "implements Cloneable" and have the base class and all sub-classes contain the clone() method. When a class has data in it that must be cloned, adding a line or two to the clone() method is very simple and straight forward.
Example
abstract public class X implements Cloneable { public Object clone() throws CloneNotSupportedException { return super.clone(); } } abstract public class Y extends X { public Object clone() throws CloneNotSupportedException { return super.clone(); } } public class Z extends Y { public Object clone() throws CloneNotSupportedException { return super.clone(); } } public class test1 { public void function() throws CloneNotSupportedException { Y varY1 = new Z(); Y varY2 = (Y) varY1.clone(); } }
Downsides
If every class in your heirarchy has a clone() method, then when the actual class is cloned, all of these functions will be called, adding what could be an enormous amount of overhead.

