Java, Programming

Using Xstream to Deep Clone Java Object

using-xstream-to-deep-clone-java-object

Sometime, We need to clone an object to save this time status for backup. If using Getter and Setter to copy the value, it must increase the source code. This method is not a good method for clone object. First, you must to know object properties. Second, if this object add more properties. You must rewrite the clone object.

Xstream is a Java library which is handle Java object convert to XML or XML convert to Java object, but also can clone java object (Java object -> XML -> Java object).

Xstream web site: http://xstream.codehaus.org/

When you download complete. Please add .jar to Class Path.

Assume there have are 2 object called: Parent and Info.

Parent class:

package xstream.sample;

public class Parent {

  private String firstName;
  private String lastName;

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

  @Override
  public String toString() {
    return "Parent [firstName=" + firstName + ", lastName=" + lastName
        + "]";
  }

}

Info class:

package xstream.sample;
import java.util.LinkedList;
import java.util.List;

public class Info {

  private String firstName;
  private String lastName;
  private int age;
  private List<String> hobbies;
  private Parent parent;

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }

  public List<String> getHobbies() {
    return hobbies;
  }

  public void setHobbies(List<String> hobbies) {
    this.hobbies = hobbies;
  }

  public void addHobby(String hobby) {
    if (hobbies == null)
      hobbies = new LinkedList<String>();
    hobbies.add(hobby);
  }

  public Parent getParent() {
    return parent;
  }

  public void setParent(Parent parent) {
    this.parent = parent;
  }

  @Override
  public String toString() {
    return "Info [firstName=" + firstName + ", lastName=" + lastName
        + ", age=" + age + ", hobbies=" + hobbies + ", parent="
        + parent + "]";
  }

}

Clone function:

package xstream.sample;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

public class Main {

private static final XStream XSTREAM = new XStream(new DomDriver());

@SuppressWarnings(“unchecked”)
public static <T> T cloneObject(T src){
return (T) XSTREAM.fromXML(XSTREAM.toXML(src));
}

}

Test case:

package xstream.sample;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

public class Main {

  private static final XStream XSTREAM = new XStream(new DomDriver());

  public static void main(String[] args) {
    //Create info object
    Info info = new Info();
    Parent parent = new Parent();

    //Set data
    info.setFirstName("Lawrence");
    info.setFirstName("Cheung");
    info.setAge(24);
    info.addHobby("Sports");
    info.addHobby("Reading");

    parent.setFirstName("Tom");
    parent.setLastName("Cheung");
    info.setParent(parent);

    //Print my info
    System.out.println("Original object: " + info);

    System.out.println("Now, we are going to clone info object");
    System.out.println();
    Info clonedInfo = cloneObject(info);

    //Print cloned info
    System.out.println("Cloned object: " + clonedInfo);
    System.out.println();

    //Modify original info
    System.out.println("Change original info age to 25 and parent first name set to John.");
    info.setAge(25);
    info.getParent().setFirstName("John");

    System.out.println();
    System.out.println("Original object: " + info);
    System.out.println("Cloned object: " + clonedInfo);
  }

  @SuppressWarnings("unchecked")
  public static <T> T cloneObject(T src){
    return (T) XSTREAM.fromXML(XSTREAM.toXML(src));
  }

}

Result:

Original object: Info [firstName=Cheung, lastName=null, age=24, hobbies=[Sports, Reading], parent=Parent [firstName=Tom, lastName=Cheung]]
Now, we are going to clone info object
Cloned object: Info [firstName=Cheung, lastName=null, age=24, hobbies=[Sports, Reading], parent=Parent [firstName=Tom, lastName=Cheung]]

Change original info age to 25 and parent first name set to John.

Original object: Info [firstName=Cheung, lastName=null, age=25, hobbies=[Sports, Reading], parent=Parent [firstName=John, lastName=Cheung]]
Cloned object: Info [firstName=Cheung, lastName=null, age=24, hobbies=[Sports, Reading], parent=Parent [firstName=Tom, lastName=Cheung]]

As you see that. The result display Info and Parent Object also cloned. I changed the original value. The cloned object also not change. So those object pointer are pointed to different address. Perfect Clone!

Tags: