This article will help you understand the basic principles and operations of serialization and deserialization.

Insert image description here


Insert image description here

1. What is serialization and deserialization?

序列化是指将对象转换为字节序列的过程,以便于存储或传输。在序列化过程中,对象的状态信息将被转换为字节流,可以保存到文件中或通过网络传输给其他计算机。反序列化则是将字节序列恢复为对象的过程。

Through deserialization, the following functions can be achieved:

对象恢复:Deserialization operations allow you to restore the state of an object from the stored byte stream. This allows the object's state to be quickly restored after the program is restarted by reading the saved byte stream and reconstructing the object.

分布式应用:In a distributed system, objects can be serialized and transferred between different computers. The receiver can convert a sequence of bytes into an operable object through a deserialization operation.

远程调用:Some remote communication frameworks use serialization and deserialization to implement remote method calls. The method call and parameters will be serialized into a byte stream and sent to the remote service, and then the method call and parameters will be restored on the remote server through deserialization.


反序列化是指将字节序列恢复为对象的过程。在序列化中,对象的状态信息被转换为字节流以便于存储或传输,而在反序列化中,这些字节流将被重新转换为原始对象的状态。

The following points need to be noted:

When deserializing, make sure the source of the byte sequence is trusted to avoid security risks.

The deserialization process may cause version compatibility issues. If, after serializing the object, the structure of the class is modified, especially deleting or changing fields, methods, etc., it may cause the object to not be restored correctly or an exception may occur during deserialization.

When deserializing, the Java virtual machine uses the default constructor in the object to create an object instance, and then uses reflection

2. Why do we need serialization and deserialization?

I still didn’t know it when I first started learning.

Serialization and deserialization are designed to transmit data.

When two processes communicate, they can be transmitted through serialization and deserialization.

持久化:The object is stored in the heap area of ​​​​the JVM, but if the JVM stops running, the object does not exist. Serialization can convert objects into byte sequences, which can be written to hard disk files for persistence. In the newly opened JVM, the byte sequence can be read and deserialized into an object.

网络传输:The network directly transmits data, but objects cannot be directly transmitted. They can be serialized before transmission and deserialized into objects after the transmission is completed. So all objects that can be transmitted over the network must be serializable.

3. Step instructions

序列化和反序列化是将对象转换为字节流或从字节流还原对象的过程。实现这两个过程的一般步骤如下:

Serialization implementation steps :

1. 确保类可以序列化:You need to check whether the class to be serialized implements Serializablethe interface. If the interface is not implemented, you need to add an implementation of the interface.

2. 创建输出流:Use an output stream (for example FileOutputStream) to write to a byte stream.

3. 创建对象输出流:Create an object output stream using ObjectOutputStreamthe class and associate it with the output stream from step 2.

4. 序列化对象:Use the object output stream writeObject()method to write the object that needs to be serialized into the byte stream.

5. 关闭流:Closes the object output stream and output stream.


Deserialization implementation steps:

1. 确保类可以反序列化:You need to check whether the class to be deserialized implements Serializablethe interface. If the interface is not implemented, you need to add an implementation of the interface.

2. 创建输入流:Use an input stream (for example FileInputStream) to read the byte stream.

3. 创建对象输入流:Create an object input stream using ObjectInputStreamthe class and associate it with the input stream from step 2.

4. 反序列化对象:Use the object input stream readObject()method to read the object from the byte stream and deserialize it.

5. 关闭流:Closes the object input stream and input stream.

4. Attention

During serialization and deserialization, it is necessary to ensure that the serialized and deserialized classes have the same serialVersionUID value to ensure version compatibility.

另外,在处理序列化和反序列化时还需要注意以下几点:

  • Static fields and fields marked transient are not serialized and deserialized.
  • Serialization may cause version compatibility issues. For example, if the structure of the class is modified after serialization, the object may not be correctly restored during deserialization.
  • Serialization and deserialization of objects may result in the constructor of the corresponding class not being called.

5. Code description

序列化

Serializable classes need to implement the java.io.Serializable interface. The interface is a marker interface without any method definitions. By implementing the Serializable interface, all non-static fields of the object can be serialized.

import java.io.*;

public class SerializationExample {
    
    
    public static void main(String[] args) {
    
    
        // 序列化对象
        try (OutputStream fileOut = new FileOutputStream("object.ser");
             ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
    
    

            Person person = new Person("Alice", 25);
            out.writeObject(person);

            System.out.println("Object serialized successfully.");

        } catch (IOException e) {
    
    
            e.printStackTrace();
        }

        // 反序列化对象
        try (InputStream fileIn = new FileInputStream("object.ser");
             ObjectInputStream in = new ObjectInputStream(fileIn)) {
    
    

            Person restoredPerson = (Person) in.readObject();
            System.out.println("Deserialized object: " + restoredPerson);

        } catch (IOException | ClassNotFoundException e) {
    
    
            e.printStackTrace();
        }
    }
}

class Person implements Serializable {
    
    
    private String name;
    private int age;

    public Person(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
    
    
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

In the above example, the Person class implements the Serializable interface so that instances of this class can be serialized. Serialize the Person object into a byte stream and save it to a file by creating an ObjectOutputStream object and calling the writeObject() method. Then by creating an ObjectInputStream object and calling the readObject() method, the byte stream can be read from the file and deserialized back to a Person object.


反序列化
Deserialization can be done through the java.io.ObjectInputStream class. This class provides the readObject() method for reading byte sequences from the input stream and deserializing them.

import java.io.*;

public class DeserializationExample {
    
    
    public static void main(String[] args) {
    
    
        // 反序列化对象
        try (InputStream fileIn = new FileInputStream("object.ser");
             ObjectInputStream in = new ObjectInputStream(fileIn)) {
    
    

            Person restoredPerson = (Person) in.readObject();
            System.out.println("Deserialized object: " + restoredPerson);

        } catch (IOException | ClassNotFoundException e) {
    
    
            e.printStackTrace();
        }
    }
}

class Person implements Serializable {
    
    
    private String name;
    private int age;

    public Person(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
    
    
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

We read the byte stream from the file named "object.ser" and deserialize it into a Person object by creating an ObjectInputStream object and calling its readObject() method. Finally, print the recovered object.

6. Principles of serialization and deserialization

序列化
1.对象图:To serialize, the entire object and the other objects it refers to form an object graph. Object diagrams represent the relationships and structures between objects.
The object diagram represents the objects involved in serialization and the relationships and structures between them. An object graph is composed of the object being serialized and the other objects it references.
For example, consider the following object diagram example for a class:

class Person implements Serializable {
    
    
    String name;
    int age;
    Address address;
}

class Address implements Serializable {
    
    
    String city;
    String street;
}

Person person = new Person();
person.name = "Alice";
person.age = 25;

Address address = new Address();
address.city = "New York";
address.street = "123 Main St";

person.address = address;

Both the Person class and the Address class implement the Serializable interface and therefore can be serialized.
An example of an object diagram is as follows:

      +------------+
      |   Person   |
      +------------+
      |   name     |
      |   age      |
      |   address--+--+
      +------------+  |
                      |
                      V
                 +------------+
                 |  Address   |
                 +------------+
                 |   city     |
                 |   street   |
                 +------------+

In the object graph, there is a Person object and an associated Address object. The Person object contains a name field, an age field and an address field, where the address field refers to an Address object. The Address object contains a city field and a street field.

When serializing, the entire object graph is recursively traversed and the state of each object is written to the byte stream. Through the object graph, the reference relationship and structure between objects can be correctly restored during deserialization.


2.写入字节流:The serialization process works by writing the state of the object (that is, the object's field values) into a byte stream. Each field of the serialized object will be written into the byte stream in a certain order to form a form that can be transmitted or stored.

这个过程涉及以下几个步骤:

  • Create an output stream: First, you need to create an output stream, which can be a file output stream, a network output stream, or other types of output streams to store the serialized byte stream.
  • Open an object stream: In Java, the ObjectOutputStream
    class is usually used as an object stream to write objects to the output stream. By passing the output stream to the constructor of the object stream, the object stream can be opened and prepared for serialization of the object.
  • Write object: Use the methods provided by the object stream, such as writeObject(Object
    obj), to write the object to be serialized into the object stream. Object streams automatically handle the serialization of objects, including writing the object's field values ​​into a byte stream in a specific format.
  • Close the stream: After completing the writing operation of the object, you need to close the object stream and output stream to release resources and ensure that the data is written correctly.

Specific code examples are as follows:

try {
    
    
    // 1. 创建输出流
    FileOutputStream fileOut = new FileOutputStream("data.ser");
    
    // 2. 打开对象流
    ObjectOutputStream objOut = new ObjectOutputStream(fileOut);
    
    // 3. 写入对象
    objOut.writeObject(person); // person 是要序列化的对象
    
    // 4. 关闭流
    objOut.close();
    fileOut.close();
    
    System.out.println("对象已成功序列化并写入字节流。");
} catch (IOException e) {
    
    
    e.printStackTrace();
}

First, a FileOutputStream object is created to represent the file output stream to be written. Then use this output stream to create an ObjectOutputStream object and open the object stream. Then call the writeObject() method to write the object person to be serialized into the object stream. Finally close the object stream and output stream.


3.对象标识:During the serialization process, in order to ensure that the same object can be restored when the same object is repeatedly referenced, an object identifier is used to uniquely identify each object. During the serialization and deserialization process, objects are associated with object identifiers to correctly restore reference relationships between objects.

In the process of object serialization and deserialization, in order to correctly restore the reference relationship and structure of the object, each serialized object needs a unique identifier.

In Java, object identification mainly relies on two mechanisms: 序列化编号(Serialization ID)和对象引用(Object References).

  • 序列化编号:Every class has a default serialization number.
    This number will be automatically generated according to the structure of the class, and a custom serialization number can be specified through the serialVersionUID field. When a class is serialized, this number is written to the serialized data. During deserialization, the read serialization number will be compared with the serialization number of the current class to determine whether it is compatible for deserialization.
    -When 对象引用:the same object or the same referenced object exists in the object graph, in order to maintain the reference relationship of the object, the referenced object will only be serialized once, and the same reference will be used when subsequently reconstructing the object. This avoids serializing the same object repeatedly and reduces the size of the serialized data.

Through the above two mechanisms, the serializer can correctly handle the identification of the object and restore the reference relationship of the object during deserialization.

It should be noted that if the structure of the class changes, such as adding, deleting, or modifying fields or methods, the original serialization number may not match the new class, which may result in incorrect deserialization. In this case, a custom serialization number should be explicitly specified and updated to ensure serialization and deserialization compatibility.


4.序列化格式:Different programming languages ​​and platforms may use different serialization formats, and the binary format is commonly used in Java. The serialization format defines how to write an object's state information to a byte stream and how to read and restore the object's state from the byte stream.


5关键方法:In Java, by implementing the Serializable interface, the serialization and deserialization of objects is automatically handled by the JVM. During the serialization process, the writeObject() method of the object will be called to write the fields; during the deserialization process, the readObject() method of the object will be called to read and restore the fields. These methods can be custom implemented as needed.


反序列化
Deserialization is the process of converting serialized data back into objects. Its implementation principle mainly involves the following steps:

Read data: Read a byte stream from serialized data.

Verify version: Verify the version information in the serialized data to ensure compatibility with the serialized version of the current program.

Create object: Create an empty object in memory based on the read data type and structure.

Read fields: Read the field values ​​stored in the serialized data sequentially, and set these values ​​into the corresponding fields of the object. These values ​​can be primitive types, reference types, or other objects.

Resolving references: If there is an object reference relationship in the serialized data, the process of resolving references will ensure that the same reference is only loaded once in the object graph to maintain the correct object reference relationship.

Execute the constructor: Execute the constructor of the object and complete the initialization of the object.

Return object: Return the complete object after deserialization.

Guess you like

Origin blog.csdn.net/m0_68987535/article/details/131566304