Friday, 3 March 2017

Deep Copy vs Shallow Copy

Shallow Copy –
Shallow copy is a bit-wise copy of an object means a new object is created with an exact copy of the values in the original object. If any of the fields of the object are references to other objects, just the reference addresses are copied

Deep Copy –
In a deep copy all fields are copied and makes copies of dynamically allocated memory pointed to by the fields. A deep copy occurs when an object is copied along with the objects to which it refers.

Shallow Copy
Deep Copy


In shallow copy only primitive variables are copied and reference variable are pointing to the same object.
In Deep copy all fields are copied primitive as well as reference variables.
To create a shallow copy we can clone the object using cloneable interface.
To create a deep copy we serialize the object.
Any changes made to cloned object will be reflected in original object or vice versa.
Any changes made to cloned object will not be reflected in original object or vice versa.
Shallow copy is preferred if an object has only primitive fields.
Deep copy is preferred if an object has reference fields as well.
Shallow copy is fast and also less expensive.
Deep copy is slow and very expensive.

Explain with Examples –
Shallow Copy –

/**
 * IN below example changing the value clone object primitive doesn't change the
 * original object but reference value changed because reference is still
 * pointing to the original object
 * @author Manoj
 */
public class ShallowCopyTest {

       public static void main(String[] args) {
              Teacher teacher = new Teacher("Teacher-CSE", "CSE");
              System.out.println("Original : " + teacher.getName() + " - " + teacher.getSubject().getName());
              // Clone as a shallow copy
              Teacher teacherClone = (Teacher) teacher.clone();
              System.out.println("CloneObjet (before change): " + teacher.getName() + " - " + teacher.getSubject().getName());

              // change the primitive member
              teacherClone.setName("Teacher-ECE");
              // change the lower-level object
              teacherClone.getSubject().setName("ECE");
              System.out.println(
                           "CloneObject (after change): " + teacherClone.getName() + " - " + teacherClone.getSubject().getName());
              System.out.println(
                           "OriginalObject (after clone is modified): " + teacher.getName() + " - " + teacher.getSubject().getName());
       }
}

class Teacher implements Cloneable {
       private Subject subject;
       private String NameOfTheTeacher;

       public Subject getSubject() {
              return subject;
       }

       public String getName() {
              return NameOfTheTeacher;
       }

       public void setName(String s) {
              NameOfTheTeacher = s;
       }

       public Teacher(String name, String subjectName) {
              NameOfTheTeacher = name;
              subject = new Subject(subjectName);
       }

       public Object clone() {
              try {
                     return super.clone();
              } catch (CloneNotSupportedException e) {
                     return null;
              }
       }
}

class Subject {

       private String name;

       Subject(String name) {
              this.name = name;
       }

       public String getName() {
              return name;
       }

       public void setName(String name) {
              this.name = name;
       }
}

Deep Copy –
Code snippet -
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* IN below example changing the value of serialized object doesn't impact into
* the original object because it is deep copied new memory allocation are created.
* pointing to the original object
* @author Manoj
*/
public class DeepCopyTest {

       public static void main(String args[]) {
              Teacher teacher = new Teacher ("Teacher-CSE", "CSE");
              System.out.println("Original : " + teacher.getName() + " - " + teacher.getSubject().getName());
              Teacher teacherClone = (Teacher) deepCopy(teacher);
              System.out.println("CloneObjet (before change): " + teacher.getName() + " - " + teacher.getSubject().getName());

              // change the primitive member
              teacherClone.setName("Teacher-ECE");
              // change the lower-level object
              teacherClone.getSubject().setName("ECE");
              System.out.println(
                           "CloneObject (after change):” + teacherClone.getName() + " - " + teacherClone.getSubject().getName());
              System.out.println(
                           "OriginalObject (after clone is modified): " + teacher.getName() + " - " + teacher.getSubject().getName());
       }
        public static Object deepCopy(Object object) {
          try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(object);
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            return ois.readObject();
          }
          catch (Exception e) {
            e.printStackTrace();
            return null;
          }
        }
}

class Teacher implements Serializable {
       private static final long serialVersionUID = 1L;
       private Subject subject;
       private String NameOfTheTeacher;

       public Subject getSubject() {
              return subject;
       }

       public String getName() {
              return NameOfTheTeacher;
       }

       public void setName(String s) {
              NameOfTheTeacher = s;
       }

       public Teacher(String name, String subjectName) {
              NameOfTheTeacher = name;
              subject = new Subject(subjectName);
       }
}
class Subject implements Serializable{

       private static final long serialVersionUID = 1L;
       private String name;

       Subject(String name) {
              this.name = name;
       }

       public String getName() {
              return name;
       }

       public void setName(String name) {
              this.name = name;
       }

}

No comments:

Post a Comment