Granting Permission Through an Interface—Cloneable

When we looked at the Object class in Chapter 3, we saw that it has this method:

protected native Object clone() throws CloneNotSupportedException;

Java supports the notion of cloning, meaning to get a complete bit-for-bit duplicate of an object. Cloning, perhaps surprisingly, does not invoke any constructor.

Not every class should support the ability to clone. If I have a class that represents a set of objects that are unique in the real world, such as the ships in a company fleet, the operation of cloning doesn't make sense. You buy new ships, but you can't get exact duplicates in every detail (including, say, registration number) of an existing ship. However, methods (including the clone() method) in the class java.lang.Object are inherited by all classes.

So Java places a further requirement on classes that want to be cloneable: They must implement the cloneable interface to indicate that cloning is valid for them. The cloneable interface is this:

public interface Cloneable { } // completely empty

The empty interface as a marker is not the most common use of interfaces, but you do see it in the system libraries. To have a class that can be cloned, you must state that the class implements the Cloneable interface.

public class ICanBeCopied implements Cloneable { ...

Why wasn't the method clone() of Object made part of the Cloneable interface? That seems like the obvious place to put it, instead of in Object. The reason is that we have two conflicting aims.

  • We want to provide a default implementation of clone so that any cloneable class can automatically inherit it. A method body cannot be put in an interface, so Object is the only possible place for it.

  • We also want individual classes to take an extra step to permit cloning on their object, so an interface is needed. The class Object has a clone() method, but does not implement the Cloneable interface, otherwise all its descendants (which is every object in existence) would too.

The end result is that we require, at minimum, an extra step of having cloneable classes implement the Cloneable interface. We provide a default implementation by putting the method clone, with a body, into the root superclass Object. That implementation does a shallow clone. If you want a deep clone, implement it in your own class. If you write your own clone(), the first statement should be a call to super.clone().

If you call clone() on an object that does not implement the Cloneable interface, you get a CloneNotSupportedException.

Note that clone() returns an Object. The object returned by clone() is usually cast immediately to the correct type, as in this example:

Vector v = new Vector();
Vector v2;

v2 = (Vector) v.clone();

Since Arrays are considered to implement the Cloneable interface, they can be copied by System.arrayCopy or by clone().

You cannot clone any enum object—java.lang.Enum disallows it with a final clone() method that throws an exception. Recall that enum constants are final values. Since they are guaranteed not to change, everyone can share one copy of them, and no duplicates are needed.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.163.197