The Clone Method

Problem

You want to clone yourself. Or at least your objects.

Solution

Override Object.clone( ) .

Discussion

To clone something is to make a duplicate of it. The clone( ) method in Java makes an exact duplicate of an object. Why do we need cloning? Java’s method calling semantics are call-by-reference, which allows the called method to modify the state of an object that is passed into it. Cloning the input object before calling the method would pass a copy of the object, keeping your original safe.

How can you clone? Cloning is not “enabled” by default in classes that you write.

Object o = new Object(  );
Object o2 = o.clone(  );

If you try calling clone( ) without any special preparation, as in this excerpt from Clone0.java, you will see a message like this (from the Jikes compiler; the javac message may not be as informative):

Clone0.java:4:29:4:37: Error: Method "java.lang.Object clone(  );" in class "java/
lang/Object" has protected or default access. Therefore, it is not accessible in 
class "Clone0" which is in a different package.

You must take two steps to make your class cloneable:

  1. Override Object’s clone( ) method.

  2. Implement the empty Cloneable interface.

Using cloning

The class java.lang.Object declares its clone protected and native . Protected classes can be called by a subclass or those in the same package (i.e., java.lang), but not by unrelated classes. That is, you can call Object.clone( ) -- the native method that does the magic of duplicating the object -- only from within the object being cloned. Here is a simple example of a class with a clone method, and a tiny program that uses it:

public class Clone1 implements Cloneable {

    /** Clone this object. Just call super.clone(  ) to do the work */
    public Object clone(  ) throws CloneNotSupportedException {
        return super.clone(  );
    }

    int x;
    transient int y;    // will be cloned, but not serialized

    public static void main(String[] args) { 
        Clone1 c = new Clone1(  );
        c.x = 100;
        c.y = 200;
        try {
            Object d = c.clone(  );
            System.out.println("c=" + c);
            System.out.println("d=" + d);
        } catch (CloneNotSupportedException ex) {
            System.out.println("Now that's a surprise!!");
            System.out.println(ex);
        }
    }

    /** Display the current object as a string */
    public String toString(  ) {
        return "Clone1[" + x + "," + y + "]";
    }
}

The clone( ) method in Object throws CloneNotSupportedException . This is to handle the case of inadvertently calling clone( ) on a class that isn’t supposed to be cloned. Since most of the time you don’t need to do anything with this exception, a clone method can simply declare this exception in its throws clause, and let the calling code deal with it.

Calling Object’s clone( ) does a stateful, shallow copy down inside the JVM. That is, it creates a new object, and copies all the fields from the old object into the new. It then returns the new reference as an Object; you need to cast it to the appropriate object type. So if that’s all there is, why do you even have to write this method? The reason is to give you a chance to do any preservation of state that is required in cloning your objects. For example, if your class has any references to other objects (and most real-world classes do), you may well want to clone them as well! The default clone method simply copies all the object’s state, so that you now have two references to each object. Or you might have to close and reopen files, to avoid having two threads (see Chapter 24) reading from or writing into the same file. In effect, what you have to do here depends on what the rest of your class does.

Now suppose that you clone a class containing an array of objects. You now have two references to objects in the array, but further additions to the array will only be made in one array or the other. Imagine a Vector, Stack, or other collection class being used in your class, and your object gets cloned!

The bottom line is that most object references need to be cloned.

Even if you don’t need clone(), your subclasses may! If you didn’t provide clone( ) in a class subclassed from Object, your subclasses will probably get the Object version, which will cause problems if there are collections or other mutable objects referred to. As a general rule, you should provide clone( ) even if only your own subclasses would need it.

Difficulty in the standard API

The java.util.Observable class (designed to implement the Model-View-Controller pattern with AWT or Swing applications) contains a private Vector but no clone method to deep-clone it. Thus, Observable objects cannot safely be cloned, ever!

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

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