Adding cloneability to a class
Even though the clone method is defined in the base-of-all-classes Object, cloning is not automatically available in every class.[118] This would seem to be counterintuitive to the idea that base-class methods are always available in derived classes. Cloning in Java does indeed go against this idea; if you want it to exist for a class, you must specifically add code to make cloning work.
Using a trick with protected
To prevent default cloneability in every class you create, the clone( ) method is protected in the base class Object. Not only does this mean that it’s not available by default to the client programmer who is simply using the class (not subclassing it), but it also means that you cannot call clone( ) via a reference to the base class. (Although that might seem to be useful in some situations, such as to polymorphically clone a bunch of Objects.) It is, in effect, a way to give you, at compile time, the information that your object is not cloneable—and oddly enough, most classes in the standard Java library are not cloneable. Thus, if you say:
Integer x = new Integer(1);
x = x.clone();
You will get, at compile time, an error message that says clone( ) is not accessible (since Integer doesn’t override it and it defaults to the protected version).
If, however, you’re in a method of a class derived from Object (as all classes are), then you have permission to call Object.clone( ) because it’s protected and you’re an inheritor. The base class clone( ) has useful functionality; it performs the actual bitwise duplication of the derived-class object, thus acting as the common cloning operation. However, you then need to make your clone operation public for it to be accessible. So, two key issues when you clone are:
- Call super.clone( )
- Make your clone
public
You’ll probably want to override clone( ) in any further derived classes; otherwise, your (now public) clone( ) will be used, and that might not do the right thing (although, since Object.clone( ) makes a copy of the actual object, it might). The protected trick works only once: the first time you inherit from a class that has no cloneability and you want to make a class that’s cloneable. In any classes inherited from your class, the clone( ) method is available since it’s not possible in Java to reduce the access of a method during derivation. That is, once a class is cloneable, everything derived from it is cloneable unless you use provided mechanisms (described later) to “turn off” cloning.
Implementing the Cloneable interface
There’s one more thing you need to do to complete the cloneability of an object: implement the Cloneable interface. This interface is a bit strange, because it’s empty!
interface Cloneable {}
The reason for implementing this empty interface is obviously not because you are going to upcast to Cloneable and call one of its methods. The use of interface in this way is called a tagging interface because it acts as a kind of flag, wired into the type of the class.
There are two reasons for the existence of the Cloneable interface. First, you might have an upcast reference to a base type and not know whether it’s possible to clone that object. In this case, you can use the instanceof keyword (described in Chapter 10) to find out whether the reference is connected to an object that can be cloned:
if(myReference instanceof Cloneable) // ...
The second reason is that mixed into this design for cloneability was the thought that maybe you didn’t want all types of objects to be cloneable. So Object.clone( ) verifies that a class implements the Cloneable interface. If not, it throws a CloneNotSupportedException exception. So in general, you’re forced to implement Cloneable as part of support for cloning.