Deep copy and serialization of Java

Source: Internet
Author: User

---restore content starts---

Copying a primitive type of variable is straightforward, assigning it directly to another object:

1 int b =; 2 int a = b;  // Basic Type Assignment

For a variable of a reference type, such as a String, the situation is slightly more complicated because the direct equals assignment only copies a copy of the reference, and the two references before and after the copy point to the same object in memory.

To implement a copy of a reference type, you can implement the Cloneable interface and override the Clone method in it.

To see an example, first define a Student class to be copied, for the sake of simplicity, only one name property is set

1 classStudentImplementscloneable{2     PrivateString name;3 4      PublicString GetName () {5         returnname;6     }7 8      Public voidsetName (String name) {9          This. Name =name;Ten     } One      A @Override -      PublicObject Clone () { -Student s =NULL; the         Try{ -s = (Student)Super. Clone (); -}Catch(Exception e) { - e.printstacktrace (); +         } -         returns; +     } A}
Student

As you can see, the Super.clone () method is actually called in the Clone method

Next copy this class, just call the Clone method:

1  Public void deepcopy () {2     New Student (); 3     S1.setname ("Zhang"); 4         5     Student s2 = (Student) S1.clone (); 6     S1.setname ("Wang"); 7     System.out.println (S1.getname ()); 8     System.out.println (S2.getname ()); 9 }
deepcopy

The output is:

WangZhang

Because S1 modifies the value of the Name property, the Name property of S1 and S2 in the output is not the same, indicating that the two references point to a different Student object, which implements the object copy.

However, if you add a reference object to the middle of the student, the copy will cause problems.

To illustrate the problem, define a car class with only one name attribute:

1 classcar{2     PrivateString name;3 4      PublicString GetName () {5         returnname;6     }7 8      Public voidsetName (String name) {9          This. Name =name;Ten     } One}
Car class definition

Modify the Student class to add a property of car type (omit this part of the code) and modify the name value of car in the Deepcopy method as follows:

1  Public voiddeepcopy () {2Student S1 =NewStudent ();3S1.setname ("Zhang");4Car car =NewCar ();5Car.setname ("Audi");6 S1.setcar (car);7         8Student s2 =(Student) S1.clone ();9S1.setname ("Wang");TenCar.setname ("BMW"); One System.out.println (S1.getname ()); A System.out.println (S2.getname ()); - System.out.println (S1.getcar (). GetName ()); - System.out.println (S2.getcar (). GetName ()); the}
Modified Deepcopy

The result of the modified output is as follows:

Wang Zhang BMW BMW

We found that there was a problem with the copy of the car type, the name value of the car property of S1 and S2 was the same, the modified BMW, which speculated that the car property of S1 and S2 pointed to the same object in memory. Verified by s1.getcar () = = S2.getcar (), the output is true, stating that the same object is actually referenced.

The problem occurs because the method above is a shallow copy method. A shallow copy is a copy of an object simply by copying its underlying type attribute, not copying the reference attribute in the object. The effect we want to achieve is to replicate with the reference type attribute in Student, which is the deep copy. A deep copy is an entire independent copy of the object, and a deep copy copies all the attributes and copies the dynamically allocated memory that the attribute points to. A deep copy occurs when the object is copied along with the object it refers to. Deep copy is slower and more expensive than shallow copy

To solve this problem, one possible way is to let the Car class also implement the Cloneable interface, and overwrite the Clone method, add a line of code in the Clone method of the Student class:

this. Car = (car) car.clone ()

This does solve the problem that Car does not replicate, however if there are more than one reference type attribute in Student, these objects may also have other reference type properties, then it is necessary to go to all related classes to implement the Cloneable interface, and overwrite the Clone method, not only troublesome, It is also very detrimental to later maintenance and expansion.

A more elegant approach is to use Java serialization and deserialization to implement deep copies. Serialization refers to the process of converting an object into a sequence of bytes, which is the process of restoring a sequence of bytes to an object. Serialization is typically used when the object persists or is transmitted over the network. "It is important to note that static and transient types of variables are not serialized"

It is simpler to make deep copies with serialization and deserialization, just to implement the Serializable interface. We can modify the student class as follows:

1 classStudentImplementsserializable{2     3     //private static final long serialversionuid = 1L;4     5     PrivateString name;6     Privatecar car;7 8      PublicCar Getcar () {9         returncar;Ten     } One  A      Public voidSetcar (car car) { -          This. Car =car; -     } the  -      PublicString GetName () { -         returnname; -     } +  -      Public voidsetName (String name) { +          This. Name =name; A     } at}
Modified Student

Temporarily ignoring the Serialversionuid property, let the car class also implement the Serializable interface, and then define a deep copy method:

1  Public voiddeepcopywithserialize () {2Student S1 =NewStudent ();3S1.setname ("zhang111");4Car car =NewCar ();5Car.setname ("Audi");6 S1.setcar (car);7         8 ObjectOutputStream oo;9     Try {TenOO =NewObjectOutputStream (NewFileOutputStream ("A.txt")); One Oo.writeobject (S1); A oo.close (); -              -ObjectInputStream Ois =NewObjectInputStream (NewFileInputStream ("A.txt"));  theStudent s2 =(Teacher) ois.readobject (); -              -S1.setname ("Wahah"); -Car.setname ("BMW"); + System.out.println (S1.getname ()); - System.out.println (S2.getname ()); + System.out.println (S1.getcar (). GetName ()); A System.out.println (S2.getcar (). GetName ()); at}Catch(IOException e) { -         //TODO auto-generated Catch block - e.printstacktrace (); -}Catch(ClassNotFoundException e) { -         //TODO auto-generated Catch block - e.printstacktrace (); in     } -          to}
deepcopywithserialize

The output is:

Wahahzhang111bmwaudi
Output Results

As you can see, a deep copy of the object is successfully implemented. Here you choose to use the file to save the serialized object, or you can choose other forms, such as Bytearrayoutputstream

1Bytearrayoutputstream BAOs =NewBytearrayoutputstream ();2ObjectOutputStream Oos =NewObjectOutputStream (BAOs);3 Oos.writeobject (S1); 4             5 //To read an object from a stream6Bytearrayinputstream Bais =NewBytearrayinputstream (Baos.tobytearray ());7ObjectInputStream Ois =NewObjectInputStream (Bais)8Student s2 = Ois.readobject ();
Serialization of Bytearrayoutputstream

Next explain the serialversionuid just ignored, according to the name know that this is a variable related to the state of the object, if the code does not define such a variable, then at run time will be automatically generated in a certain way, at the time of deserialization will be judged on this value, If two values are not equal, a invalidclassexception is thrown. Since the calculation of the default serialversionuid is highly sensitive to the details of the class, it is generally recommended to provide this parameter proactively at serialization time.

Summary

The Clone method of the ①cloneable interface is a shallow copy by default and requires a self-overwrite to achieve a deep copy.

It is simpler to implement deep copies using Serializable serialization, but you need to be aware of the values that define SERIALVERSIONUID, and variables of static and transient types are not serialized ②.

Resources

The contents of this article mainly refer to the following blog, here to express our thanks

Benson's column-java How to copy objects

Tamu-Deep Clone

Please call me big bro.-java Serializable The concept of serialization and deserialization, the function of the understandable explanation

Keyword transient in Java

Java serialization exclusion is serialized field (transient/static variable)

Deep copy and serialization of Java

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.