Monday, 23 January 2012

Copying Java Objects: Shallow copy and Deep copy

This post gives you overview different type of object copying mechanism in JAVA.

Shallow Copy

  This is done using clone() method in any class. When you clone the object using clone() method, (of course the class of object type should implement cloneable interface before you do this) a new object is created and the instance variables are newly created. If all the instance variables of the object are of primitive data type, then no work is needed inside clone() method other than calling super.clone().

Please take a close look at the following example, in which instance variable of type "StringBuffer" is just copied while cloning and not created newly. The output shows any modification to the value of this instance variable affects both the original and cloned object.

package samples.clone;

public class ShallowCopySample implements Cloneable
{
 private String myName;
 private int mySalary;
 private StringBuffer myFamilyMembers = new StringBuffer().append("K").append("P");
 public StringBuffer getMyFamilyMembers()
 {
  return myFamilyMembers;
 }
 public void setMyFamilyMembers(StringBuffer myFamilyMembers)
 {
  this.myFamilyMembers = myFamilyMembers;
 }
 public String getMyName()
 {
  return myName;
 }
 public void setMyName(String myName)
 {
  this.myName = myName;
 }
 public int getMySalary()
 {
  return mySalary;
 }
 public void setMySalary(int mySalary)
 {
  this.mySalary = mySalary;
 }

 ShallowCopySample(String name, int salary)
 {
  this.myName = name;
  this.mySalary = salary;
 }

 @Override
 protected Object clone() throws CloneNotSupportedException
 {
  return super.clone();
 }
 public static void main(String[] args) throws CloneNotSupportedException
 {
  ShallowCopySample scs1 = new ShallowCopySample("Suresh", 50000);
  System.out.println("SCS1 before cloning:"+scs1.getMyName()+","+scs1.getMySalary());

  // shallow cloning
  ShallowCopySample scs2 = (ShallowCopySample)scs1.clone();
  scs2.setMySalary(30000);
  scs2.setMyName("Transmode");
  scs2.setMyFamilyMembers(scs2.getMyFamilyMembers().append("A"));

  System.out.println("SCS1 after cloning:"+scs1.getMyName()+","+scs1.getMySalary()+","+scs1.getMyFamilyMembers());
  System.out.println("SCS2 after cloning:"+scs2.getMyName()+","+scs2.getMySalary()+","+scs2.getMyFamilyMembers());
 }
}

The output of the above program is,

 
SCS1 before cloning:Suresh,50000
SCS1 after cloning:Suresh,50000,KPA
SCS2 after cloning:Transmode,30000,KPA



Deep Copy

  This is nothing but serialization of object, the class should implement java.io.Serializable interface. This copies the object through stream of bytes or writes the object into a file. It ensures that original and cloned object instances and it's instance variables are different.
Note: The serialization mechanism is used in Java RMI.

Please take a close look at the following example,

package samples.clone;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class DeepCopySample implements Serializable
{
 /**
  *
  */
 private static final long serialVersionUID = 1L;
 private String myName;
 private int mySalary;
 private StringBuffer myFamilyMembers = new StringBuffer().append("K").append("P");

 public StringBuffer getMyFamilyMembers()
 {
  return myFamilyMembers;
 }
 public void setMyFamilyMembers(StringBuffer myFamilyMembers)
 {
  this.myFamilyMembers = myFamilyMembers;
 }
 public String getMyName()
 {
  return myName;
 }
 public void setMyName(String myName)
 {
  this.myName = myName;
 }
 public int getMySalary()
 {
  return mySalary;
 }
 public void setMySalary(int mySalary)
 {
  this.mySalary = mySalary;
 }

 DeepCopySample(String name, int salary)
 {
  this.myName = name;
  this.mySalary = salary;
 }
 /**
  * copy the object using stream of bytes serializable mechanism
  * @param orig
  * @return
  */
 public static Object copy(Object orig) {
        Object obj = null;
        try {
            // Write the object out to a byte array
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(bos);
            out.writeObject(orig);
            out.flush();
            out.close();
            // Make an input stream from the byte array and read
            // a copy of the object back in.
            ObjectInputStream in = new ObjectInputStream(
                new ByteArrayInputStream(bos.toByteArray()));
            obj = in.readObject();
        }
        catch(IOException e) {
            e.printStackTrace();
        }
        catch(ClassNotFoundException cnfe) {
            cnfe.printStackTrace();
        }
        return obj;
    }

 public static void main(String[] args) {
  DeepCopySample dcs1 = new DeepCopySample("Suresh", 50000);

  System.out.println("DCS1 before cloning:"+dcs1.getMyName()+","+dcs1.getMySalary());

  // deep cloning
  DeepCopySample dcs2 = (DeepCopySample)DeepCopySample.copy(dcs1);
  dcs2.setMySalary(30000);
  dcs2.setMyName("Transmode");
  dcs2.setMyFamilyMembers(dcs2.getMyFamilyMembers().append("A"));

  System.out.println("DCS1 after cloning:"+dcs1.getMyName()+","+dcs1.getMySalary()+","+dcs1.getMyFamilyMembers());
  System.out.println("DCS2 after cloning:"+dcs2.getMyName()+","+dcs2.getMySalary()+","+dcs2.getMyFamilyMembers());
 }
}

The output of the above program is,
DCS1 before cloning:Suresh,50000
DCS1 after cloning:Suresh,50000,KP
DCS2 after cloning:Transmode,30000,KPA

No comments:

Post a Comment