Tuesday, 29 October 2013

Inside Story Of Cloning


How Cloning Works ...





·         In Java, when you assign an object to another variable, only the memory address of the object is copied and hence any changes in the original object will be reflected in the new variable.
MainObject obj1 = new MainObject();        obj2 = obj1;
·         Now cloning comes into picture, when if you don’t want to copy memory address and expecting to copy content values.
So what is cloning?
·         Cloning means creating a copy of the object.
This copy of an object can be achieved through the Copy Contractor.
What is copy-constructor?
·         A copy constructor is one that takes object of its own type as a single parameter.
EX:
public class Person {
    private Car car;
    private String name;
    public Person(Car c, String n)    {
        car = c;
        name = n;
    }
    public Person(Person p)
    {
        name = p.name;
        car = new Car(p.car);
        // we assume we have a copy
        //constructor for Car
    }
    public String toString()    {
        return "This is person has " + car;
    }
}
public class Car {
    public Car() {}
}
public class CopyConstructorMain {

    public static void main(String [] args) {

        Person person1 = new Person(new Car(), "Ben");
        Person person2 = new Person(person1);
        System.out.println(person1);
        System.out.println(person2);
    }
}

Output is:
----------
This is person has Car@4edbb0
This is person has Car@3f75e0
      
      ·         There is a limitation with the copy constructor, like if the variable "car" in Person class is actually an instance of a subclass “Benz” then you will get the wrong answer; what is called a slice.
·         To avoid this problem we have cloning concept now.

How do you implement cloning in java?
      ·         Implement “Cloneable” interface.  (The class registers with the JVM to get permission for cloning)
      ·         Override “clone()” method with a try-catch block for CloneNotSupportedException.

What is Shallow Copy?
  • Shallow copy is a bit-wise copy of an object.
  • The class variables and associated values will be copied fine.
  • But if we have any other class object and respective references, then only reference memory address will be copied for new cloned object.
  • When you copy the "ColoredCircle" using clone() method, the fields x and y are copied perfectly with values but field "color" is copied by reference.
  • So any changes you make to the color of the original object will be reflected in the copied object and vice versa.
  • To avoid that, we have deep copy.

  • What is Deep Copy?
  • The class variables and associated values will be copied fine.
  • And also references and associated objects will be copied.
  • So changes done in both the classes are independent.
  • Change the Color class to implement "Cloneable" interface and clone() method and call the clone() method of color object inside the clone() method of the ColoredCircle object.
  • Look at the changed Color class and ColoredCircle class below.

Shallow Copy
Deep Copy
public class Color {

    private String color;

    public Color(String c){
        this.color = c;
    }

    //getters and setters for the fields should go here........
}

public class ColoredCircle implements Cloneable {

    private int centerX;
    private int centerY;
                private Color color;

                public ColoredCircle(int x, int y, Color c){
                    this.centerX = x;          
                                this.centerY = y;
                                this.color = c;
                }

    public Object clone() {
        try {
            return (ColoredCircle)super.clone();
        }
        catch (CloneNotSupportedException e) {
            // This should never happen
        }
    }

    //getters and setters for the fields should go here........
}

public class CloneMain {

    public static void main(String [] args) {

Color c = new Color("RED");
ColoredCircle c1 = new ColoredCircle(200,200,c);
ColoredCircle c2 = c1.clone();
    }
}
public class Color implements Cloneable{

    private String color;

    public Color(String c){
        this.color = c;
    }

    public Object clone() {
        try {
            return (Color)super.clone();
        }
        catch (CloneNotSupportedException e) {
            // This should never happen
        }
    }

    //getters and setters for the fields should go here........
}

public class ColoredCircle implements Cloneable {

    private int centerX;
    private int centerY;
    private Color color;

    public ColoredCircle(int x, int y, Color c){
        this.centerX = x;      
        this.centerY = y;
        this.color = c;
    }

    public Object clone() {
        ColoredCircle coloredCircle = null;
        try {
           coloredCircle = (ColoredCircle)super.clone();
        }
        catch (CloneNotSupportedException e) {
            // This should never happen
        }
        coloredCircle.color = (Color) color.clone();
        return coloredCircle;
    }

    //getters and setters for the fields should go here........
}

  • Deep copy can be achieved through serialization, but only limitation is Transient variables will not be copied properly.

Question: if clone is a protected method then why the sub class has to implement Cloneable interface type to use its super class method?
Answer: clone is a dangerous method. So by implementing Cloneable interface you are telling JVM that "There is a good reason to clone my class, so please allow me".
Note:
     ·         While making use of Object clone() method, it will just returns Object type, so this is our responsibility to Type cast to Our class type.

When to do shallow copy and deep copy?
  ·         It’s very simple that if the object has only primitive fields, then obviously you will go for shallow copy.
  ·         But if the object has references to other objects, then based on the requirement, shallow copy or deep copy should be chosen.
  ·         What I mean here is, if the references are not modified anytime, and then there is no point in going for deep copy. You can just opt shallow copy.
   ·         But if the references are modified often, then you need to go for deep copy. Again there is no hard and fast rule; it all depends on the requirement.

Lazy copy:
  ·         A lazy copy is a combination of both shallow copy and deep copy.
  ·         When initially copying an object, a (fast) shallow copy is used. 
  ·         When the program wants to modify the original object, it can determine if the data is shared (by examining the counter) and can do a deep copy at that time if necessary.
  ·          Lazy copy looks to the outside just as a deep copy but takes advantage of the speed of a shallow copy whenever possible.

No comments :

Post a Comment