Recently, I have compiled the basic knowledge of java, and the information on java serialization and deserialization has been sorted out in detail. I will take a note here, hoping that it will also help friends who read this article.
1. The concept of serialization and deserialization
The process of converting an object into a sequence of bytes is called the serialization of an object.
The process of restoring a sequence of bytes into an object is called deserialization of an object.
There are two main uses for serialization of objects:
1) Save the byte sequence of objects permanently on the hard disk, usually in a file;
2) Transfer the byte sequence of objects on the network.
In many applications, certain objects need to be serialized, so that they leave the memory space and move on to the physical hard drive for long-term storage. For example, the most common one is the Session object in the Web server. When 100,000 users access concurrently, 100,000 Session objects may appear, and the memory may not be able to bear it. Therefore, the web container will serialize some seesions to the hard disk first, and wait until it is used, and then restore the objects saved in the hard disk to the memory.
When two processes are communicating remotely, they can send various types of data to each other. No matter what type of data is, it will be transmitted on the network in the form of a binary sequence. The sender needs to convert this Java object into a sequence of bytes in order to be transmitted on the network; the receiver needs to restore the bytes into a Java object.
2. Serialization API in JDK class library
java.io.ObjectOutputStream represents the object output stream. Its writeObject(Object obj) method can serialize the obj object specified by the parameter and write the obtained byte sequence to a target output stream.
java.io.ObjectInputStream represents the object input stream. Its readObject() method reads byte sequences from a source input stream, deserializes them into an object, and returns them.
Only objects of classes that implement Serializable and Externalizable interfaces can be serialized. The Externalizable interface inherits from the Serializable interface. The classes that implement the Externalizable interface completely control the serialization behavior, while classes that only implement the Serializable interface can adopt the default serialization method.
Object serialization includes the following steps:
1) Create an object output stream, which can wrap another type of target output stream, such as file output stream;
2) Write the object through the writeObject() method of the object output stream.
The steps for deserializing an object are as follows:
1) Create an object input stream that can wrap a different type of source input stream, such as file input stream;
2) Read the object through the readObject() method of the object input stream.
Object serialization and desequencing examples:
Define a Person class to implement the Serializable interface
1 import java.io.Serializable; 2 3 /** 4 * <p>ClassName: Person<p> 5 * <p>Description: Test object serialization and deserialization<p> 6 * @author xudp 7 * @version 1.0 V 8 * @createTime 2014-6-9 02:33:25 pm 9 */10 public class Person implements Serializable {11 12 /**13 * Serialization ID14 */15 private static final long serialVersionUID = -5809782578272943999L;16 private int age;17 private String name;18 private String sex;19 20 public int getAge() {21 return age;22 }23 24 public String getName() {25 return name;26 }27 28 public String getSex() {29 return sex;30 }31 32 public void setAge(int age) {33 this.age = age;34 }35 36 public void setName(String name) {37 this.name = name;38 }39 40 public void setSex(String sex) {41 this.sex = sex;42 }43 }Serialize and deserialize Person class objects
import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.text.MessageFormat;/** * <p>ClassName: TestObjSerializeAndDeserialize<p> * <p>Description: Serialization and deserialization of test objects<p> * @author xudp * @version 1.0 V * @createTime 2014-6-9 03:17:25 pm */public class TestObjSerializeAndDeserialize { public static void main(String[] args) throws Exception { SerializePerson();//Serialize Person object Person p = DeserializePerson();//Deserial Perons object System.out.println(MessageFormat.format("name={0},age={1},sex={2}", p.getName(), p.getAge(), p.getSex())); } /** * MethodName: SerializePerson * Description: Serialize Person object* @author xudp * @throws FileNotFoundException * @throws IOException */ private static void SerializePerson() throws FileNotFoundException, IOException { Person person = new Person(); person.setName("gacl"); person.setAge(25); person.setSex("Male"); // ObjectOutputStream object output stream, store the Person object in the Person.txt file on the E disk, and complete the serialization operation of the Person object. ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream( new File("E:/Person.txt"))); oo.writeObject(person); System.out.println("Person object serialization was successfully! "); oo.close(); } /** * MethodName: DeserializePerson * Description: DeserializePerson object* @author xudp * @return * @throws Exception * @throws IOException */ private static Person DeserializePerson() throws Exception, IOException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("E:/Person.txt"))); Person person = (Person) ois.readObject(); System.out.println("Person object deserialization successfully!"); return person; }}The code run results are as follows:
After serializing Person successfully, a Person.txt file was generated on E disk, while deserializing Person is used to read Person.txt of E disk.
3. The role of serialVersionUID
serialVersiUID: literally means serialized version number. All classes that implement the Serializable interface have a static variable representing the serialized version identifier.
private static final long serialVersionUID
If serialVersionUID is not added to the class, the following warning will appear.
Clicking with the mouse will bring up a dialog box that generates serialVersionUID, as shown in the figure below:
There are two ways to generate serialVersionUID:
The serialVersionUID generated in this way is 1L, for example:
private static final long serialVersionUID = 1L;
The serialVersionUID generated in this way is generated based on class name, interface name, method and attribute, etc., for example:
private static final long serialVersionUID = 4603642343377807741L;
After adding, the warning will not appear, as shown below:
After talking about it, what is the use of serialVersionUID (serialized version number)? Let’s use the following example to illustrate the role of serialVersionUID, and see the following code:
1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.FileNotFoundException; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 import java.io.ObjectInputStream; 7 import java.io.ObjectOutputStream; 8 import java.io.Serializable; 9 10 public class TestSerialversionUID {11 12 public static void main(String[] args) throws Exception {13 SerializeCustomer();// Serialize Customer object 14 Customer customer = DeserializeCustomer();// Deserial Customer object 15 System.out.println(customer);16 }17 18 /**19 * MethodName: SerializeCustomer 20 * Description: Serialize Customer object 21 * @author xudp22 * @throws FileNotFoundException23 * @throws IOException24 */25 private static void SerializeCustomer() throws FileNotFoundException,26 IOException {27 Customer customer = new Customer("gacl",25);28 // ObjectOutputStream Object output stream29 ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(30 new File("E:/Customer.txt")));31 oo.writeObject(customer);32 System.out.println("Customer object serialization successfully!");33 oo.close();34 }35 36 /**37 * MethodName: DeserializeCustomer 38 * Description: DeserializeCustomer object 39 * @author xudp40 * @return41 * @throws Exception42 * @throws IOException43 */44 private static Customer DeserializeCustomer() throws Exception, IOException {45 ObjectInputStream ois = new ObjectInputStream(new FileInputStream(46 new File("E:/Customer.txt")));47 Customer customer = (Customer) ois.readObject();48 System.out.println("Customer object deserialization was successful! ");49 return customer;50 }51 }52 53 /**54 * <p>ClassName: Customer<p>55 * <p>Description: Customer implements the Serializable interface and can be serialized<p>56 * @author xudp57 * @version 1.0 V58 * @createTime 2014-6-9 04:20:1759 pm */60 class Customer implements Serializable {61 //No serialVersionUID62 private String name;63 private int age;64 65 public Customer(String name, int age) {66 this.name = name;67 this.age = age;68 }69 70 /*71 * @MethodName toString72 * @Description Rewrite the toString() method of the Object class 73 * @author xudp74 * @return string75 * @see java.lang.Object#toString()76 */77 @Override78 public String toString() {79 return "name=" + name + ", age=" + age;80 }81 }Running results:
Both serialization and deserialization were successful.
Let’s modify the Customer class and add an additional sex attribute, as follows:
1 class Customer implements Serializable { 2 //No serialVersionUID is defined in the Customer class 3 private String name; 4 private int age; 5 6 //New sex attribute 7 private String sex; 8 9 public Customer(String name, int age) {10 this.name = name;11 this.age = age;12 }13 14 public Customer(String name, int age,String sex) {15 this.name = name;16 this.age = age;17 this.sex = sex;18 }19 20 /*21 * @MethodName toString22 * @Description Rewrite the toString() method of the Object class 23 * @author xudp24 * @return string25 * @see java.lang.Object#toString()26 */27 @Override28 public String toString() {29 return "name=" + name + ", age=" + age;30 }31 }Then perform the desequence operation, and the following exception information will be thrown:
1 Exception in thread "main" java.io.InvalidClassException: Customer; 2 local class incompatible: 3 stream classdesc serialVersionUID = -88175599799432325, 4 local class serialVersionUID = -5182532647273106745
This means that the class in the file stream and the class in the classpath, that is, the modified class, are incompatible. They are under the security mechanism considerations. The program throws an error and refuses to load. So what if we really have a need to add a field or method after serialization? What should I do? That is to specify the serialVersionUID yourself. In the TestSerialversionUID example, if the serialVersionUID of the Customer class is not specified, then the java compiler will automatically perform a summary algorithm for this class, similar to the fingerprint algorithm. As long as the file has one more space, the resulting UID will be completely different, which can be guaranteed that this number is unique among so many classes. Therefore, after adding a field, since the serialVersionUID is not specified, the compiler generates a UID for us, which is of course not the same as the one saved in the file before, so there are two errors with inconsistent serialization version numbers. Therefore, as long as we specify serialVersionUID ourselves, we can add a field or method after serialization without affecting the later restoration. The restored object can still be used, and there are also more methods or attributes to use.
Next, continue to modify the Customer class and specify a serialVersionUID to Customer. The modified code is as follows:
class Customer implements Serializable { /** * serialVersionUID (serialized version number) defined in Customer class */ private static final long serialVersionUID = -5182532647273106745L; private String name; private int age; //New sex attribute//private String sex; public Customer(String name, int age) { this.name = name; this.age = age; } /*public Customer(String name, int age,String sex) { this.name = name; this.age = age; this.sex = sex; }*/ /* * @MethodName toString * @Description Rewrite the toString() method of the Object class* @author xudp * @return string * @see java.lang.Object#toString() */ @Override public String toString() { return "name=" + name + ", age=" + age; }}Re-execute the serialization operation, serialize the Customer object to the Customer.txt file storage on the local hard disk, then modify the Customer class and add the sex attribute. The modified Customer class code is as follows:
class Customer implements Serializable { /** * serialVersionUID (serialized version number) defined in Customer class */ private static final long serialVersionUID = -5182532647273106745L; private String name; private int age; //New sex attribute private String sex; public Customer(String name, int age) { this.name = name; this.age = age; } public Customer(String name, int age,String sex) { this.name = name; this.age = age; this.sex = sex; } /* * @MethodName toString * @Description Rewrite the toString() method of the Object class* @author xudp * @return string * @see java.lang.Object#toString() */ @Override public String toString() { return "name=" + name + ", age=" + age; }}Perform the desequence operation, and the desequence will be successful this time, as shown below:
4. The value of serialVersionUID
The value of serialVersionUID is automatically generated by the Java runtime environment based on the internal details of the class. If the source code of the class is modified and recompiled, the value of the serialVersionUID of the newly generated class file may also change.
The default value of the serialVersionUID of a class depends entirely on the implementation of the Java compiler. For the same class, compiling with different Java compilers may lead to different serialVersionUIDs, and may also be the same. To improve the independence and certainty of serialVersionUID, it is strongly recommended to define serialVersionUID displayed in a serializable class, assigning it a clear value.
There are two purposes for explicitly defining serialVersionUID:
1. In some cases, it is expected that different versions of the class are compatible with serialization, so it is necessary to ensure that different versions of the class have the same serialVersionUID;
2. In some cases, different versions of the class are not expected to be compatible with serialization, so it is necessary to ensure that different versions of the class have different serialVersionUIDs.
Thank you for reading, I hope it can help you. Thank you for your support for this site!