This is the 24th day of my participation in the First Challenge 2022

Serialization and deserialization is the most basic knowledge in Java, and it is easy to forget, although it is used every day, but not always clearly explained. I’m sure many of you know only a few concepts and keywords (Serializable), but if you ask how serialization and deserialization are implemented, how to use scenarios, etc., you may feel overwhelmed. Every time I look at Java fundamentals as an interviewer, I usually ask about serialization and deserialization to gauge how Java fundamentals are. When asked what is Java serialization? What is deserialization? In what situations will it be used? If you do not use it, what problems will appear, etc., we generally answer is a few simple concepts, some work for several years even the concept of the applicant can not say clearly, a face of boredom.

In this article, serialization and deserialization are discussed in depth, so that when asked by others, you will not feel embarrassed and embarrassed, and may increase your bargaining chip in the future job interview.

1. Basic Concepts

1. What is serialization and deserialization

Serialization is the process of converting a Java object into a sequence of bytes, while deserialization is the process of converting a sequence of bytes into a Java object.

Java object serialization is the implementation of Serializable interface objects into a sequence of bytes, can be transmitted through network transmission, file storage, etc., without worrying about the change of data in different machines, different environments, byte order or any other details. The byte sequence can be completely restored to its original object at a later date (a process called deserialization).

Object serialization is interesting because it allows for lightweight persistence, which means that the life of an object depends not only on whether the program is running, but also between calls to the program. The persistence of an object is achieved by writing a serialized object to disk and then restoring it when the program is called again.

In essence, serialization is to write the entity object state to the ordered byte stream in a certain format, and deserialization is to rebuild the object from the ordered byte stream and restore the object state.

2. Why serialization and deserialization

As we know, when different processes/programs communicate remotely, they can send various types of data to each other, including text, pictures, audio, video, etc., and these data will be transmitted over the network in the form of binary sequences.

When two Java processes communicate, can object transfer be implemented between processes? Of course it can! How do you do that? This requires the use of Java serialization and deserialization. The sender needs to convert the Java object into a sequence of bytes and transfer it over the network, and the receiver needs to recover the Java object from the sequence of bytes.

Now that we know why we need to use Java serialization and deserialization, it’s natural to think about the benefits of Java serialization:

  • The realization of data persistence, through serialization can be permanently stored on the hard disk (such as: stored in a file), to achieve permanent storage objects.
  • Remote communication using serialization, that is, the ability to transfer objects over a network.

How to implement Java serialization and deserialization

An object implements serialization as long as it implements the Serializable, Externalizable**** interface, which is simply a tag interface and does not contain any methods.

1. How is this implemented?

To serialize, you create some OutputStream objects and wrap them in an ObjectOutputStream. Call writeObject() to serialize the object and send it to the OutputStream (object serialization is bytes-based, So InputStream and OutputStream inherit classes).

Deserialization, the process of serializing in reverse, involves wrapping an InputStream inside an ObjectInputStream and then calling the readObject() method to get an Object reference (which points to an upturned Object), A type cast is then performed to obtain the object.

Given a User class whose objects need to be serialized, there are three methods:

(1) If the User class only implements the Serializable interface, it can be serialized and deserialized as follows.

ObjectOutputStream serializes the non-transient instance variables of the User object using the default serialization method.

ObjcetInputStream uses the default deserialization method to deserialize non-transient instance variables of the User object.

(2) If the User class only implements Serializable interface and also defines readObject(ObjectInputStream in) and writeObject(ObjectOutputSteam Out), The following methods are used for serialization and deserialization.

ObjectOutputStream calls the writeObject(ObjectOutputStream out) method of the User object for serialization. ObjectInputStream will deserialize the User object by calling its readObject(ObjectInputStream in) method.

(3) If the User class implements Externalnalizable interface, and the User class must implement readExternal(ObjectInput in) and writeExternal(ObjectOutput Out) methods, Serialization and deserialization are performed as follows.

ObjectOutputStream calls the writeExternal(ObjectOutput Out) method of the User object for serialization.

ObjectInputStream calls the User object’s readExternal(ObjectInput in) method for deserialization.

  • Java. IO. ObjectOutputStream: output stream Object, its writeObject (Object obj) method can be serialized to the specified Object obj, to get the sequence of bytes to a target output stream.
  • Java. IO. ObjectInputStream: object input stream, its readObject () method can be read from the input stream sequence of bytes, then to deserialize them into an object, and returns it.

Serialization and deserialization examples

To better understand the serialization and deserialization process, the following is an example:

public class SerialDemo {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
	// serialize the object User
        FileOutputStream fos = new FileOutputStream("object.txt");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        User user1 = new User("xcbeyond"."123456789");
        oos.writeObject(user1);
        oos.flush();
        oos.close();

	// deserialize
        FileInputStream fis = new FileInputStream("object.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        User user2 = (User) ois.readObject();
        System.out.println(user2.getUsername()+ ","+ user2.getPassword()); }}Copy the code
// Object User, to which the Serializable interface is implemented
public class User implements Serializable {
    private String username;
    privateString password; ... }Copy the code

3. When is serialization required

  • When you want to save the state of an object in memory to a file or database.
  • When you want to send objects over the network using a socket.
  • When you want to transfer objects over RMI.

Three, notes

1. When a parent class implements serialization, subclasses automatically implement Serializable interface without explicitly implementing it.

2. When an instance variable of an object refers to another object, the reference object is serialized when the object is serialized.

Not all objects can be serialized. For example:

  • For security reasons, such as an object has private, public and other member variables. For an object to be transferred, such as writing to a file or RMI transfer, the private domain of the object is not protected during serialization transmission.

  • For resource allocation reasons, such as socket and Thread classes, if they can be serialized, transferred, or saved, they cannot be re-resourced, and it is not necessary to do so.

4. Member variables declared static and transient cannot be serialized. Static represents the state of the class and transient represents the temporary data of the object.

5. The serialization runtime uses a version number called serialVersionUID, associated with each serializable class, which is used during deserialization to verify that the sender and receiver of the serialized object loaded a serialization-compatible class for the object. If the serialVersionUID of the object’s class loaded by the receiver is different from the version number of the corresponding sender’s class, deserialization will result in an InvalidClassException. Serializable classes can explicitly declare their own serialVersionUID by declaring a field named “serialVersionUID” (which must be a static, final, long field).

If the serialized class does not explicitly declare serialVersionUID, the serialization runtime calculates the default serialVersionUID value for the class based on aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare the serialVersionUID value, because calculating the default serialVersionUID is highly sensitive to class details and can vary widely depending on compiler implementations, This can result in an unexpected InvalidClassException during deserialization. Therefore, to ensure consistency of the serialVersionUID value across different Java compiler implementations, the serialized class must declare an explicit serialVersionUID value. It is also strongly recommended to display the declaration serialVersionUID with the private modifier, if possible, because this declaration only applies to directly declared classes — the serialVersionUID field is not useful as an inherited member. Array classes cannot declare an explicit serialVersionUID, so they always have a default computed value, but the array class does not match the requirement for a serialVersionUID value.

6. Java has many base classes that implement serializable interfaces, such as String, Vector, etc. However, some do not implement the Serializable interface.

If the member variable of an object is an object, the data members of that object are also saved! This is an important reason serialization can be used to solve deep copy.

With this detailed introduction to serialization and deserialization, you now have a more in-depth understanding of how to implement serialization and deserialization in your daily life, and in what situations to use it


Reference:

  • Java Programming Ideas by Bruce Eckel, Translated by Haopeng Chen
  • What is the underlying implementation of serialization and deserialization? What is Serialization
  • 【Java】Serializable and deserialized _Mr_EvanChen Blog-CSDN Blog