We all know that easiest way of deep cloning (with some performance overhead) or deep copy is Serialization. Java serialization involves serializing the object into bytes and from bytes to object again.
I will suggest you to use in memory deep cloning whenever it is the only need and you don’t need to persist the object for future use. In this Java deep cloning example, I will suggest one mechanism of in-memory deep cloning for your reference.
Please remember that deep cloning is evil for singleton pattern. It makes possible of having multiple instances of singleton classes.
Read more : Java Object Cloning Guide
1. Java deep copy example
In demonstration program, I have created a demo class named SerializableClass
. This has three variables i.e. firstName
, lastName
and permissions
. I will add a deepCopy() instance level method to this class. Whenever invoked on an instance of SerializableClass
, it will return exact clone / deep copy of that instance.
For deep cloning, we have to first serialization and then deserialization. For serialization, I have used ByteArrayOutputStream
and ObjectOutputStream
. For deserialization, I have used ByteArrayInputStream
and ObjectInputStream
.
package serializationTest; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.List; public class SerializableClass implements Serializable { private static final long serialVersionUID = 1L; private String firstName = null; private String lastName = null; @SuppressWarnings("serial") private List permissions = new ArrayList() { { add("ADMIN"); add("USER"); } }; public SerializableClass(final String fName, final String lName) { //validateNameParts(fName); //validateNameParts(lName); this.firstName = fName; this.lastName = lName; } public SerializableClass deepCopy() throws Exception { //Serialization of object ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bos); out.writeObject(this); //De-serialization of object ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream in = new ObjectInputStream(bis); SerializableClass copied = (SerializableClass) in.readObject(); //Verify that object is not corrupt //validateNameParts(fName); //validateNameParts(lName); return copied; } 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 new StringBuilder().append(getFirstName()+",") .append(getLastName()+",") .append(permissions) .toString(); } }
2. Demo
Lets test the class and create deep copy of instance to verify if it works as expected.
package serializationTest; public class ImMemoryTest { public static void main(String[] args) throws Exception { //Create instance of serializable object SerializableClass myClass = new SerializableClass("Lokesh","Gupta"); //Verify the content System.out.println(myClass); //Now create a deep copy of it SerializableClass deepCopiedInstance = myClass.deepCopy(); //Again verify the content System.out.println(deepCopiedInstance); } }
Program Output.
Lokesh,Gupta,[ADMIN, USER] Lokesh,Gupta,[ADMIN, USER]
Before considering in-memory deep copy objects in your application, you might like to read about serialization guidelines which will prevent your design from breaking in future.
Happy Learning !!
Read More:
Shallow copy vs deep copy in Java
Srenivas
Hi ,
How do we compare or Verify that object is not corrupt.
harry
Excellent article! But, one query –
In
method, you made a comment –
I wonder, what could possibly go wrong and what can we do to verify/tackle it?
Punith
The same implementation is achieved through Apache commons utils..
http://grepcode.com/file/repo1.maven.org/maven2/commons-lang/commons-lang/2.4/org/apache/commons/lang/SerializationUtils.java
rohit padhee
can you explain the flow of the program? like what is happening first and what is happening in second?
Lokesh Gupta
Rohit, program is very simple. In first program, Instead of writing the byte stream to any file/network resource, I am directly using to create another instance of class. This saved me lots of I/O operations.
Second program is just an example for how to use code of first program.
rohit padhee
thanks for getting back, as we are not using lots of file I/O operations, I guess that is an advantage of deep cloning ? and why we are using deep cloning? I know its mentioned if we dont want to persist the object for future use but here we are creating another duplicate object . didnt get this part..
Lokesh Gupta
It means we are creating a clone of object to further use in application. We do not intent to store in database (some applications store whole object after serializing it instead writing tabular data).
rohit padhee
Great!! now I got it , Thanks for the explanation
harry
Excellent article. But, one query –
You have a comment in the code //Verify that object is not corrupt
I wonder, what could possibly go wrong and how we verify/tackle it?