Copy object or clone object?

How is difference between copy and clone object? First we check what is copy.

Copy

Create CloneObject project.

In projects window in netrbeans You see tree of your project. You have only main class(CloneObject.java file).

You may right click on cloneobject package and choose New->Java Class.

In Class Name field write Person. It will be our experimental object.

In tree of project You see Person.java file – your new class.

Paste into Person.java file this code:

package cloneobject;
public class Person
{
   private String name;
   private int points;
   
   public Person(String name)
   {
    this.name = name;
   }
   public int getPoints()
   {
     return points;  
   }
   public void setPoints(int points)
   {
     this.points = points;  
   }
}

This class have one field name. You don’t change this field. Person have fixed name. But in this class is either points field, but it is changeable. You may call setPoints method to change points field. You may read this value to call getPoints method.

Next step paste this code into main class:

package cloneobject;
public class CloneObject {
    public static void main(String[] args) {
        Person orgin = new Person("Kate");
        orgin.setPoints(23);
        System.out.println("points in orgin after orgin.setPoints(23) = "+orgin.getPoints());
        Person copy = orgin;
        System.out.println("points in copy after copy = orgin = "+copy.getPoints());
        copy.setPoints(27);
        System.out.println("points in orgin after copy.setPoints(27) = "+orgin.getPoints());
        System.out.println("points in copy after copy.setPoints(27) = "+copy.getPoints());
    } 
}

You create Person object.  In next line You set 23 points for this person. And You create second Person object reference to your first object. This object is the copy of your first object. For copy call setPoints method to change points. The points in copy object was changed to 27, but in orgin object points field was changed either.

Run application to check this thougth:

So, if You would like ta have separate object, You must create not copy, but clone this object. Test this.

Clone

You may change Person.java file. Paste into it this code:

package cloneobject;
public class Person implements Cloneable
{
   private String name;
   private int points;
   
   public Person(String name)
   {
    this.name = name;
   }
   public int getPoints()
   {
     return points;  
   }
   public void setPoints(int points)
   {
     this.points = points;  
   }
   public Person clone() throws CloneNotSupportedException
   {
       return (Person) super.clone();
   }
}

This class must implement Cloneable interface. This interface has clone method to implement, so you must create this method. This method must throws CloneNotSupportedException. Method must return current object.

Then in main class paste this code:

package cloneobject;
public class CloneObject {
    public static void main(String[] args) {
        try{
        Person orgin = new Person("Kate");
        orgin.setPoints(23);
        System.out.println("points in orgin after orgin.setPoints(23) = "+orgin.getPoints());
        Person clone = orgin.clone();
        System.out.println("points in clone after clone = orgin = "+clone.getPoints());
        clone.setPoints(27);
        System.out.println("points in orgin after clone.setPoints(27) = "+orgin.getPoints());
        System.out.println("points in clone after clone.setPoints(27) = "+clone.getPoints());
        orgin.setPoints(28);
        System.out.println("points in orgin after orgin.setPoints(28) = "+orgin.getPoints());
        System.out.println("points in clone after orgin.setPoints(28) = "+clone.getPoints());
        } catch(CloneNotSupportedException e){}
    }
}

In this method to new Person object is reference to clone of orginal object, because is calling clone method. Calling clone method must be in try – catch clouse, because this method may return exception: CloneNotSupportedException.

Run application to test.

In this screeen You see that change in clone object don’t change field in orginal object and change in orginal object don’t change in clone object. But it is only for basic datatype and objects definition in Java library. What is with field of your implemented classes?

Go testing it.

Clone object contains changing object

In cloneobject package create new class: Hobby. So right click on this package node and choose New->Java Class.

In Class Name field write Hobby and click on Finish button.

Paste into Hobby.java file this code:

 package cloneobject;
public class Hobby
{
  private String name;
  private int years;
  public Hobby(String name, int years)
  {
   this.name = name;
   this.years = years;
  }

  public String toString()
  {
      return name+" - years "+years;
  }
}

Every person must have either hobby. So in Person class add two another method:

public Hobby getHobby()
   {
     return hobby;  
   }
   public void setHobby(Hobby hobby)
   {
     this.hobby = hobby;  
   } 

And field in class:

private Hobby hobby;

In main class call setHobby method and getHobby method for orginal and clone object. Paste in it new code:

package cloneobject;
public class CloneObject {
    public static void main(String[] args) {
        try{
        Person orgin = new Person("Kate");
        orgin.setHobby(new Hobby("swim",2));
            System.out.println("--------orgin set hobby swim 2");
        System.out.println("hobby in orgin  = "+orgin.getHobby().toString());
        Person clone = orgin.clone();
            System.out.println("--------clone clone orgin object");
        System.out.println("hobby in clone  = "+clone.getHobby().toString());
        clone.setHobby(new Hobby("ski",4));
            System.out.println("--------clone set hobby ski 4");
        System.out.println("hobby in orgin  = "+orgin.getHobby().toString());
        System.out.println("hobby in clone  = "+clone.getHobby().toString());
        orgin.setHobby(new Hobby("basketball",5));
            System.out.println("--------orgin set hobby basketball 5");
        System.out.println("hobby in orgin  = "+orgin.getHobby().toString());
        System.out.println("hobby in clone  = "+clone.getHobby().toString());
        } catch(CloneNotSupportedException e){}
    }   
}

Run this application.

Calling setHobby method for clone object don’t change object field in orginal Person object and calling setHobby method for orginal object, don’t change Hobby field in clone object.

Clone object with fields of basic or another objects type don’t change orginal object.

Clone object contains changing object with changing its fields

First go to Hobby.java file and paste this code into it:

package cloneobject;
public class Hobby
{
  private String name;
  private int years;
 
  public Hobby(String name, int years)
  {
   this.name = name;
   this.years = years;
  }
  public String getName()
  {
      return name;
  }
  public int getYears()
  {
      return years;
  }
  public void setName(String name)
  {
      this.name = name;
  }
  public void setYears(int years)
  {
      this.years = years;
  }
}

In this file you add method: setName, setYears and getName, getYears. Delete toString method.

Change code in CloneObject.java file. Paste into it this code:

package cloneobject;
public class CloneObject {
public static void main(String[] args) {
try{
Person orgin = new Person("Kate");
orgin.setHobby(new Hobby("swim",2));
System.out.println("--------orgin set hobby swim 2");
System.out.println("hobby in orgin  = "+orgin.getHobby().getName()+", "+orgin.getHobby().getYears());
Person clone = orgin.clone();
System.out.println("--------clone clone orgin object");
System.out.println("hobby in clone  = "+clone.getHobby().getName()+", "+clone.getHobby().getYears());
clone.getHobby().setName("ski");
System.out.println("--------clone set name for last hobby as ski");
System.out.println("hobby in orgin  = "+orgin.getHobby().getName()+", "+orgin.getHobby().getYears());
System.out.println("hobby in clone  = "+clone.getHobby().getName()+", "+clone.getHobby().getYears());
orgin.getHobby().setYears(12);
System.out.println("--------orgin set years hobby as 12");
System.out.println("hobby in orgin  = "+orgin.getHobby().getName()+", "+orgin.getHobby().getYears());
System.out.println("hobby in clone  = "+clone.getHobby().getName()+", "+clone.getHobby().getYears());
} catch(CloneNotSupportedException e){}
}
}

Run application:

In this situation you see that change Hobby object in clone object changing either orginal object. In the same way work changing in Hobby object in  orginal object. This change either clone object. How resolve this problem?

Resolving is deep clone.

Go to Hobby.java file and add implements Cloneable interface and add clone method for it:

package cloneobject;
public class Hobby implements Cloneable
{
private String name;
private int years;
public Hobby(String name, int years)
{
this.name = name;
this.years = years;
}
public String getName()
{
return name;
}
public int getYears()
{
return years;
}
public void setName(String name)
{
this.name = name;
}
public void setYears(int years)
{
this.years = years;
}
public Hobby clone() throws CloneNotSupportedException
{
Hobby cloned = (Hobby) super.clone();
return cloned;
}
}

And change clone method in Person.java file for this:

public Person clone() throws CloneNotSupportedException
   {
       Person cloned = (Person)super.clone();
       cloned.hobby = (Hobby) hobby.clone();
       return cloned;
   }

In that way Person object clones all field and  either all Hobby object fields.

Run application:

Here if clone object change field in Hobby object it is change only for clone object. Orginal object has old data. If you change Hobby field in orginal object change is only for orginal object, clone object has old data.