Showing posts with label SHALLOW COPY. Show all posts
Showing posts with label SHALLOW COPY. Show all posts

Thursday, 24 February 2011

Clone, Cloneable, Deep and Shallow Clone


CLONE and CLONEABLE:
Clone is a protected method defined in Object class. To clone any class that class should must implement Cloneable interface which is a marker interface otherwise it will through CloneNotSupportedException. 
Cloneable is a marker interface so no method defined. Interesting thing is it does not support Generics probably because it was there before Generics or for backward compatibility.
Cloneable Vs Serialization:
Cloneable interface is used to make a clone of a object,every time create a new instance by new operator is costly in terms of JVM ,resource & performance. so we can create similar type of instance with the help of already been created instance by using clone()


Serialization is a process to convert your object into bitstream and send accross the network and deserialze at other end,process like Marshling. By default serialization dies Deep Copy.



SHALLOW COPY vs DEEP COPY:
Shallow copies duplicate as little as possible. A shallow copy of a collection is a copy of the collection structure, not the elements. With a shallow copy, two collections now share the individual elements.
Deep copies duplicate everything. A deep copy of a collection is two collections with all of the elements in the original collection duplicated.

How to do SHALLOW COPY:
For shallow copy we can clone() method but make sure all field reference classes should also be Cloneable.

How to do DEEP COPY:

Solution 1: Use Copy Constructor

class DeepCloneableClass {
   //Define other constructor as usual

   //Copy Constructor for deep cloning
   public DeepCloneableClass(DeepCloneableClass from){
      this.field1  = from.getField1();
      ...
      ...
   }
}


Solution 2: Use Factory Pattern 

class DeepCloneableClass {

//Create factory method for deep cloning
    public static DeepCloneableClass fromInstance(DeepCloneableClass from){
        new DeepCloneableClass(from.getFeild1());
        ...
    }
}

Solution 3: Force by new Interface like DeepCloneable


interface DeepCloneable<T>{            
    //In implementaion create deep copy
    public T deepClone(T t);
}



Example Showing Difference Between Deep and Shallow Copy:
************************************************

package com.object;


class Person implements Cloneable {
// Lower-level object
private Car car;


private String name;


public Car getCar() {
return car;
}


public String getName() {
return name;
}


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


public Person(String s, String t) {
name = s;
car = new Car(t);
}


public Object deepClone() {
// Deep copy
Person p = new Person(name, car.getName());
return p;
}


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


class Car {


private String name;


public String getName() {
return name;
}


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


public Car(String s) {
name = s;
}
}


public class DeepNShallowCopyTest {


public static void main(String[] args) {
// Original Object
Person p = new Person("Person-A", "Civic");
System.out.println("Original (orginal values): " + p.getName() + " - "
+ p.getCar().getName());


// Clone as a shallow copy
Person q = (Person) p.shallowClone();


System.out.println("Clone (before change): " + q.getName() + " - "
+ q.getCar().getName());


// change the primitive member
q.setName("Person-B");


// change the lower-level object
q.getCar().setName("Accord");


System.out.println("Clone (after change): " + q.getName() + " - "
+ q.getCar().getName());


System.out.println("Original (after clone is modified): " + p.getName()
+ " - " + p.getCar().getName());


System.out.println("********************************");


// Original Object
Person dp = new Person("Person-A", "Civic");
System.out.println("Original (orginal values): " + dp.getName() + " - "
+ dp.getCar().getName());


// Clone as a shallow copy
Person dq = (Person) dp.deepClone();


System.out.println("Clone (before change): " + dq.getName() + " - "
+ dq.getCar().getName());


// change the primitive member
dq.setName("Person-B");


// change the lower-level object
dq.getCar().setName("Accord");


System.out.println("Clone (after change): " + dq.getName() + " - "
+ dq.getCar().getName());


System.out.println("Original (after clone is modified): "
+ dp.getName() + " - " + dp.getCar().getName());


}
}

OUTOUT :

Original (orginal values): Person-A - Civic
Clone (before change): Person-A - Civic
Clone (after change): Person-B - Accord
Original (after clone is modified): Person-A - Accord
********************************
Original (orginal values): Person-A - Civic
Clone (before change): Person-A - Civic
Clone (after change): Person-B - Accord
Original (after clone is modified): Person-A - Civic