Home : Course Map : Chapter 8 : Java : Supplements :
Cloning
JavaTech
Course Map
Chapter 8

Introduction
Threads Overview
  Demo 1   Demo 2
Stopping Threads
Multi-Processing
Thread Tasks
Animations
 
 Demo 3   Demo 4  
  Demo 5

Non-interacting
  Demo 6

Task Splitting
  Demo 7

Exclusivity
  Demo 8

Communicating
  Demo 9

Priority/Scheduling
More Thread

Exercises

    Supplements
Java2D Animation
  Demo 1 
Processor View
More Concurrency
Cloning
  Demo 2  Demo 3 

     About JavaTech
     Codes List
     Exercises
     Feedback
     References
     Resources
     Tips
     Topic Index
     Course Guide
     What's New

Making a copy of an object seems at first to be a straight forward task:

Simply copy the values of all the properties into another instance of the same class.

But what about the variables that are references to other objects? Copies of these reference values mean they will point to the same objects as the first class.

But maybe that is not what we want. Perhaps we want all the objects referenced by the copy to be independent copies as well.

These two types of object copies are called:

  • shallow copy - exact bit copy of all the attributes of the original object
  • deep copy - primitives are copied exactly but objects referenced are copied rather than the references themselves.

The Object class, which is inherited by all Java classes, includes the clone() method that will make exact bit copies of all the properties.

However, clone() is a protected method. So a given object can not be cloned by instances of any classes outside the package (unless they are subclasses of that object's class). This allows the class designer to specify explicitly what kind of clones (shallow or deep) to make.

Java requires classes that want to override the clone() method, to implement the cloneable interface. The clone() method must be made public as well so as to override the access restrictions.

For example, the HashTable class implements cloneable. Its clone() method makes a shallow copy so the keys and values of the copied HashTable will reference the same objects as the original.

Many core Java classes, however, do not implement cloneable. If the clone() method is invoked for such classes, a CloneNotSupportedException will result.

Example.java

import java.util.*;

/** Illustrate cloning instances of a class. **/
public class Example implements Cloneable {
  int fNum;
  Integer [] fIarray;

  Example (int nElements) {
    fNum = nElements;
    fIarray = new Integer[fNum];

    // Set the array to random values
    Random ran = new Random ();
    for (int i=0; i < fNum; i++){
      fIarray[i] = new Integer (ran.nextInt (10000));
    }

  } // const

  public Object clone () {
    try  {
      return super.clone ();
    }
    catch (CloneNotSupportedException e) {
      throw new Error ("This should never happen!");
    }
  } // clone

  public static void main (String [] args)
  {
    Example ex   =  new Example (5);
    Example copy =  (Example)ex.clone ();

    // Change a value in the original array.
    ex.fIarray[0] = new Integer (1234567);

    // Then the copy's value also changes since it references
    // the same array.
    System.out.println ("Original iarray[0] = " + ex.fIarray[0]);
    System.out.println ("Copy     iarray[0] = " + copy.fIarray[0]);
  } // main

} // Example

ExampleDeep.java

/** Illustrate cloning a subclass of a cloneable class. **/
public class ExampleDeep extends Example {

  ExampleDeep (int num) {
    super (num);
  } // const

  public Object clone () {

  // First make exact bitwise copy
    ExampleDeep copy =  (ExampleDeep)super.clone ();

    // A new array of references to Integer objects
    // is created
    copy.fIarray = new Integer[copy.fNum];

    // Then the new Integer objects given same internal
    // values as the original
    for (int i=0; i < copy.fNum; i++) {
      copy.fIarray[i] =
          new Integer (fIarray[i].intValue ());
    }
    return copy;
  } // clone

  public static void main (String [] args)
  {
    ExampleDeep ex   =  new ExampleDeep (5);
    ExampleDeep copy =  (ExampleDeep) ex.clone ();

    // Change a value in the original array.
    ex.fIarray[0] = new Integer (1234567);

    // But  the copy's value unchanged since it references
    // a different array.
    System.out.println ("Original iarray[0] = " + ex.fIarray[0]);
    System.out.println ("Copy     iarray[0] = " + copy.fIarray[0]);

  } // main

} // ExampleDeep

 

For the Example case:

c:\> java Example
Original iarray[0] = 1234567
Copy iarray[0] = 1234567

While for the DeepExample case, a typical run goes as:

c:\> java Example
Original iarray[0] = 1234567
Copy iarray[0] = 1930

We see that the deep copy creates a separate array of Integer objects.

Applet Cloning Demo

The following applet illustrates the same techniques


CloningJApplet8
Illustrates these same concepts in a graphical interface.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

/** Include Outputable interface if needed. **/
public class CloningJApplet8 extends JApplet
             implements ActionListener
{
  // A Swing fTextArea for display of string info
  JTextArea fTextArea ;

  // Flag for whether the applet is in a browser
  // or running via the main () below.
  boolean fInBrowser = true;

  ShallowClass fShallowClass;
  DeepClass fDeepClass;

  public void init () {

    // Create a User Interface with a TextArea with sroll bars
    // and a Go button to initiate processing and a Clear button
    // to clear the TextArea.

    JPanel panel = new JPanel (new BorderLayout ());

    // Create an instance of a fTextArea
    fTextArea = new JTextArea ();
    fTextArea.setEditable (false);

    // Add to a scroll pane so that a long list of
    // computations can be seen.
    JScrollPane area_scroll_pane = new JScrollPane (fTextArea);

    panel.add (area_scroll_pane,"Center");

    JButton go_button = new JButton ("Shallow");
    go_button.addActionListener (this);

    JButton clear_button = new JButton ("Deep");
    clear_button.addActionListener (this);

    JButton exit_button = new JButton ("Exit");
    exit_button.addActionListener (this);

    JPanel control_panel = new JPanel ();
    control_panel.add (go_button);
    control_panel.add (clear_button);
    control_panel.add (exit_button);

    panel.add (control_panel,"South");
    // Add text area with scrolling to the content pane.
    add (panel);

  } // init

  // Can use the start () method, which is called after
  // init () and the display has been created.
  public void start () {
    // Put task code here that will generate text
    // for the fTextArea.
  } // start

  public void actionPerformed (ActionEvent e) {
    String source = e.getActionCommand ();
    if ( source.equals ("Shallow"))
        shallowClone ();
    else if ( source.equals ("Deep") )
        deepClone ();
    else if (!fInBrowser)
        System.exit (0);
  } // actionPerformed

  public void shallowClone () {
    ShallowClass copy;

    fShallowClass = new ShallowClass (5);
    copy =  (ShallowClass)fShallowClass.clone ();

    // Modify original data
    fShallowClass.setData (4, 1234567);
    output ("Original = ", fShallowClass);
    output ("Clone    = ", copy);
  } // shallowClone

  public void deepClone () {
    DeepClass copy;
    fDeepClass = new DeepClass (5);

    copy =  (DeepClass)fDeepClass.clone ();

    // Modify original data
    fDeepClass.setData (4, 12345767);
    output ("Original = ", fDeepClass);
    output ("Clone    = ", copy);

  } // deepClone

  public void output (String str, ShallowClass obj) {
    fTextArea.append (str);
    Integer [] data = obj.getData ();
    for (int i=0; i < 5; i++)
       fTextArea.append (data[i]+" ");
    fTextArea.append ("\n");
  } // output

  public static void main (String[] args) {
    // *** Modify these values for the particular program.
    int frame_width=350;
    int frame_height=350;

    // *** Modify applet subclass name to that of the program
    CloningJApplet8 applet = new CloningJApplet8 ();
    applet.fInBrowser = false;

    // Note that init () invoked before adding to frame.
    // So don't use width/height info in init () since those
    // parameters not yet set.
    applet.init ();

    // Following anonymous class used to close window & exit program
    JFrame f = new JFrame ("Frame & Image Demo");
    f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
    // Add applet to the frame

    f.getContentPane ().add (applet);
    f.setSize (new Dimension (frame_width,frame_height));
    f.setVisible (true);
  }
} // main

class ShallowClass implements Cloneable {

  Integer [] fData = null;
  int fNumData = 5;

  ShallowClass ()
  {}

  ShallowClass (int num) {
    fNumData = num;
    makeData ();
  }

  ShallowClass (Integer [] dat) {
    fData = dat;
  }

  void makeData () {
    Random ran = new Random ();
    fData = new Integer[fNumData];
    for (int i=0; i < fNumData; i++)
    {
      fData[i] = new Integer (ran.nextInt (10000));
    }
  } // makeData

  Integer [] getData () {
    return fData;
  }

  void setData (int element, int val) {
    if (element < fNumData)
       fData[element] = new Integer (val);
  }

  public Object clone (){
    try {
      // The clone's data is same as the original
      return  (ShallowClass)super.clone ();
    }
    catch  (CloneNotSupportedException e ) {
      throw new Error ("This should never happen!");
    }
  }
} // ShallowClass

class DeepClass extends ShallowClass {
  DeepClass ()
  { }

  DeepClass (int num)
  { super (num); }

  DeepClass (Integer [] dat)
  { super (dat);}

  void setData (Integer [] dat)
  { fData = dat;}

  public Object clone (){
    // First make copy of the data
    Integer [] clone_data = new Integer[fNumData];
    for (int i=0; i < fNumData; i++) {
      // New Integer objects but same values
      clone_data[i] = new Integer (fData[i].intValue () );
    }

    // Create a new instance of DeepClass with
    // the new data array.

      DeepClass copy =  (DeepClass)super.clone ();
      copy.setData (clone_data);
      return copy;
  } // clone

} // DeepClass

 

 

Most recent update: Sept. 16, 2005

              Tech
Timers
  Demo 1
Hist. Adapt Range
  Demo 2
Sorting in Java
  Demo 3
Histogram Median
  Demo 4
Refactoring
  Demo 5
Error Bars
  Demo 6
Exercises

           Physics
Least Squares Fit
  Demo 1
Fit to Polynomial
  Demo 2
Fit Hist Errors
  Demo 3
Discretization
  Demo 4
Timing
  Demo 5
Exercises

  Part I Part II Part III
Java Core 1  2  3  4  5  6  7  8  9  10  11  12 13 14 15 16 17
18 19 20
21
22 23 24
Supplements

1  2  3  4  5  6  7  8  9  10  11  12

Tech 1  2  3  4  5  6  7  8  9  10  11  12
Physics 1  2  3  4  5  6  7  8  9  10  11  12

Java is a trademark of Sun Microsystems, Inc.