Using
clone( ) and the Cloneable Interface
Most of the methods defined
by Object are discussed elsewhere in
this book. However, one deserves special attention: clone( ). The clone( )
method generates a duplicate copy of the object on which it is called. Only
classes that implement the Cloneable
interface can be cloned.
The Cloneable interface defines no members. It is used to indicate that
a class allows a bitwise copy of an object (that is, a clone) to be made. If you try to call clone( ) on a class that does not implement Cloneable, a CloneNotSupportedException
is thrown. When a clone is made, the constructor for the object being cloned is
not called. As implemented by Object, a clone is simply an exact copy
of the original.
Cloning is a potentially
dangerous action, because it can cause unintended side effects. For example, if
the object being cloned contains a reference variable called obRef, then when the clone is made, obRef in the clone will refer to the
same object as does obRef in the
original. If the clone makes
a change to the contents of the object referred to by obRef, then it will be changed for the original object, too. Here
is another example: If an object opens an I/O stream and is then cloned, two
objects will be capable of operating on the same stream. Further, if one of
these objects closes the stream, the other object might still attempt to write
to it, causing an error. In some cases, you will need to override the clone( ) method defined by Object to handle these types of
problems.
Because cloning can cause
problems, clone( ) is declared as protected inside Object. This means that it must either be called from within a
method defined by the class that implements Cloneable, or it must be explicitly overridden by that class so
that it is public. Let’s look at an example of each approach.
The following program
implements Cloneable and defines the
method cloneTest( ), which calls clone( ) in Object:
// Demonstrate the clone() method
class TestClone implements Cloneable { int a;
double b;
// This method calls Object's clone().
TestClone cloneTest() {
try {
// call clone in Object.
return (TestClone) super.clone();
} catch(CloneNotSupportedException e) {
System.out.println("Cloning not allowed."); return this;
}
}
}
class CloneDemo {
public static void main(String args[]) {
TestClone x1 = new TestClone(); TestClone x2;
x1.a = 10; x1.b = 20.98;
x2 = x1.cloneTest(); // clone x1
System.out.println("x1: " + x1.a +
" " + x1.b); System.out.println("x2: " + x2.a + "
" + x2.b);
}
}
Here, the method cloneTest( ) calls clone( ) in Object and
returns the result. Notice that the object returned by clone( ) must be cast into its appropriate type (TestClone).
The following example
overrides clone( ) so that it can be
called from code outside of its class. To do this, its access specifier must be
public, as shown here:
// Override the clone() method.
class TestClone implements Cloneable { int a;
double b;
// clone() is now overridden and is public.
public Object clone() {
try {
// call clone in Object.
return super.clone();
} catch(CloneNotSupportedException e) {
System.out.println("Cloning not allowed."); return this;
}
}
}
class CloneDemo2 {
public static void main(String args[]) {
TestClone x1 = new TestClone(); TestClone x2;
x1.a = 10; x1.b = 20.98;
// here, clone() is called directly.
x2 = (TestClone) x1.clone();
System.out.println("x1: " + x1.a +
" " + x1.b);
System.out.println("x2: " + x2.a +
" " + x2.b);
}
}
The side effects caused by
cloning are sometimes difficult to see at first. It is easy to think that a
class is safe for cloning when it actually is not. In general, you should not
implement Cloneable for any class
without good reason.
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.