In-depth understanding of the Serializable interface

Initial impression of Serializalbe

Serializalbe frequently used J AVA entity object when "implements Serializable", is generally known to implement this interface is serialized. So what is the purpose of serialization?

View Serializalbe interface source code

java.ioSerializable { 
}

It is an empty interface, which can be seen as an iconic interface. The annotation indicates that the class that does not implement this interface will not perform any serialization or deserialization of its state, and the JVM uses this identifier to identify whether it needs to be serialized.

Serializable interface overview

Serializable is a semantic level interface defined in the java.io package and used to implement the serialization operation of Java classes. The Serializable serialization interface does not have any methods or fields, but is used to identify the semantics of serialization. A class that implements the Serializable interface can be converted into a byte stream by ObjectOutputStream, and it can also be parsed into an object through ObjectInputStream. For example, after writing a serialized object to a file, we can read it from the file again and deserialize it into an object, that is, we can use the type information and bytes representing the object and its data to recreate the object in memory.

And this is very important for object-oriented programming languages, because no matter what programming language, the underlying part of the IO operation is still done by the operating system, and the underlying IO operations are all byte streams. So the write operation involves converting the programming language data type into a byte stream, and the read operation involves converting the byte stream into a specific data type of the programming language type. Java is an object-oriented programming language, and objects are the type carriers of its main data. In order to complete the read and write operations of object data, a way is needed to let the JVM know how to convert the object data into IO operations. Byte stream, and how to convert byte stream data into a specific object, and the Serializable interface assumes such a role.

An experiment, Show me the code

【experiment one】

We can use examples to store the serialized object to a file, and then deserialize it from the file to an object. The code example is as follows:

First define a serialized object User:

User Serializable {
    Integer String (Integer idString name) {
        .= id.= name}

First test to write the object to a file (this uses SpringBoot to establish an accessible interface, and executes the file write operation when accessing this interface):

HelloWorldController {
    (= = RequestMethod.)
    User (String name) {
        User user = User(name){
            ObjectOutputStream objectOutputStream = ObjectOutputStream(FileOutputStream())objectOutputStream.writeObject(user)objectOutputStream.close()} (IOException e) {
            e.printStackTrace()}


        user}
}

After accessing this interface (my local address): http://127.0.0.1:8080/hello/say  , we write the User object and the data it carries into the text test.txt:

image.png

See that the object data is persisted to the disk file.

[Experiment 2]

Remove the Serializable interface in the entity class

User{
    Integer String (Integer idString name) {
        .= id.= name}

Run the interface again, and the error is as follows:

image.pngA NotSerializableException exception is thrown, prompting a non-serializable exception, which means that an object that does not implement the Serializable interface cannot be persisted through IO operations, because the JVM does not automatically convert the object into a byte stream, so no operation is done in the program At this time, the user object cannot be directly stored in the persistence layer.

【Experiment three】

Convert the object data previously persisted into the test.txt file into Java objects again, the code is as follows:


About serialization and deserialization

Serialization: The process of converting a Java object into a byte stream. It is the process of turning these objects in memory into a series of bytes (bytes) description.

Deserialization: The process of converting a byte stream into a Java object.

scenes to be used

1, the memory needed to save the state of the image data to a file or database, when prepared for example when we use mybatis persistence layer frame insert object data into the database

2. When network communication needs to use sockets to transmit objects in the network, such as when we use RPC protocol for network communication


Supplement (taken from other websites)

About serialVersionUID

For the JVM, the class to be persisted must have a mark. Only with this mark can the JVM allow the object created by the class to be converted into byte data through its IO system to achieve persistence, and this mark is Serializable interface. In the process of deserialization, you need to use the serialVersionUID to determine which class to load the object, so when we implement the Serializable interface, we generally have to define the serialVersionUID as explicitly as possible, such as:

private static final long serialVersionUID = 1L;

在反序列化的过程中,如果接收方为对象加载了一个类,如果该对象的serialVersionUID与对应持久化时的类不同,那么反序列化的过程中将会导致InvalidClassException异常。例如,在之前反序列化的例子中,我们故意将User类的serialVersionUID改为2L,如:

private static final long serialVersionUID = 2L;

那么此时,在反序例化时就会导致异常,如下:

java.io.InvalidClassException: cn.wudimanong.serializable.User; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2     at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:687)     at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1880)     at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1746)     at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2037)     at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1568)     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:428)     at cn.wudimanong.serializable.SerializableTest.readObj(SerializableTest.java:31)     at cn.wudimanong.serializable.SerializableTest.main(SerializableTest.java:44)

If we do not explicitly declare the serialVersionUID in the serialization, the serialization runtime will calculate the default serialVersionUID value of the class according to various aspects of the class. However, Java officially strongly recommends that all classes to be serialized explicitly declare the serialVersionUID field, because if it is highly dependent on the JVM to generate the serialVersionUID by default, it may cause it to be coupled with the implementation details of the compiler, which may lead to the deserialization An unexpected InvalidClassException occurred during the process. Therefore, in order to ensure the consistency of the serialVersionUID values ​​implemented across different Java compilers, those who implement the Serializable interface must explicitly declare the serialVersionUID field.

In addition, the declaration of the serialVersionUID field should be modified as much as possible with the private keyword. This is because the declaration of this field only applies to the declared class. It is useless for this field to be inherited by subclasses as a member variable! There is a special place that needs to be noted. , Array classes cannot explicitly declare serialVersionUID, because they always have the value calculated by default, but the requirement to match the serialVersionUID value is also abandoned during the deserialization of the array class.



Guess you like

Origin blog.51cto.com/13238147/2667199