Java foundation - IO stream 3_ Object flow

Posted by jnoun on Tue, 04 Jan 2022 17:38:13 +0100

1, Object flow

1. Serialization and deserialization

Serialization: save Java objects in memory to disk or transfer them over the network.
Deserialization: restores an object in a disk file to a Java object in memory.

Purpose:
(1) save the object to the physical hard disk: for example, when 100000 users access the Session object in the Web server concurrently, 100000 Session objects may appear, and the memory may not be enough, resulting in OOM. So the Web container will serialize some sessions to the hard disk, and then deserialize the objects in the hard disk to memory when necessary.
(2) transmission of objects on the network: when two processes communicate, data will be transmitted on the network in the form of binary sequence. The sender needs to convert the Java object into a byte sequence before it can be transmitted on the network; The receiver needs to restore the byte sequence to a Java object.

2,ObjectOutputStream,ObjectInputStream

Byte stream, processing stream. ObjectOutputStream and ObjectInputStream, which are used to store and read processing streams of basic data types or objects. Its strength is that it can write objects in Java to the data source and restore objects from the data source.
Serialization: a mechanism for holding basic type data or objects with the ObjectOutputStream class.
Deserialization: a mechanism for reading basic type data or objects with the ObjectInputStream class.
Note: member variables decorated with static and transient cannot be serialized.

How to serialize?
(1) the interface must be implemented: Serializable, which is an identification interface without any abstract method to indicate that the class is Serializable.
(2) define a global constant: serialVersionUID, which is optional and used to identify the version number of the class.
(3) if the class has class attributes: all attributes of the class must be serializable.
Code example: Standard Template

1 public class Person implements Serializable {
2     private static final long serialVersionUID = 1L;
3 }

Code example: serialization and deserialization

 1 // serialize.object->disk
 2 public class Main {
 3     public static void main(String[] args) {
 4         try (FileOutputStream stream = new FileOutputStream("Obj.dat");
 5              // Object output stream
 6              ObjectOutputStream oos = new ObjectOutputStream(stream);) {
 7 
 8             oos.writeObject("For test serialization");
 9             oos.writeObject(new Person(1001, "Zhang San", new Account(11.1)));
10         } catch (Exception e) {
11         }
12     }
13 }
14 
15 // Deserialization.disk->object
16 public class Main {
17     public static void main(String[] args) {
18         try (FileInputStream stream = new FileInputStream("Obj.dat");
19              // Object input stream
20              ObjectInputStream ois = new ObjectInputStream(stream);) {
21 
22             String str = (String) ois.readObject();
23             Person p = (Person) ois.readObject();
24 
25             System.out.println(str);
26             System.out.println(p);
27         } catch (Exception e) {
28         }
29     }
30 }
31 
32 
33 class Person implements Serializable {
34     public static final long serialVersionUID = 1L;
35     private int id;
36     private String name;
37     // private transient double hight; // Serialization is not required
38     private Account acct; // acct Property must also be serializable
39 
40     // Parameterless constructor
41     // Parametric constructor
42     // getter & setter
43     // toString()
44 }
45 
46 class Account implements Serializable {
47     public static final long serialVersionUID = 1L;
48     private double balance;
49 
50     // Parameterless constructor
51     // Parametric constructor
52     // getter & setter
53     // toString()
54 }

Summary (important):
(1) if the interface Serializable is not implemented, it will directly report Java io. Notserializableexception exception.
(2) implement Serializable, but do not write serialVersionUID. There will be no exceptions, but there will be hidden problems. If the class has been serialized, the structure of the class is modified. For example, if a new attribute is added, an error will be reported when deserializing.
(3) if an attribute in the class does not want to be serialized, the keyword transient can be added.

3. Understanding of serialVersionUID

If not

  private static final long serialVersionUID = 1L;

First serialize the class, then modify the structure of the class (for example, add a new field), and then deserialize it. The errors reported are as follows:

  java.io.InvalidClassException: temp.file.Person; local class incompatible: stream classdesc serialVersionUID = 503624515100475858, local class serialVersionUID = -443494311322032311

serialVersionUID: sequenced version number. All classes that implement the Serializable interface have a static variable representing the serialized version identifier to indicate the compatibility between different versions of the class.
If the class does not show the definition of this static variable, its value is automatically generated by the Java runtime environment according to the internal details of the class. If the structure of the class is modified, the class in the file stream is incompatible with the class in the classpath. Considering the security mechanism, the program throws an exception and refuses to load.
Solution: to solve the above problem, you only need to explicitly declare serialVersionUID.
Since the serialVersionUID is used during serialization, does it not need to define the serialVersionUID attribute if no instance of the abstract class is serialized? The fact is that the description of the parent class will be obtained recursively during serialization, so if the serialVersionUID of the parent class is modified, the deserialization of the child class object will also fail.

Topics: Java