1 Overview Object serialization refers to the process of converting an object into a byte sequence, while deserialization refers to the process of recovering an object based on the byte sequence. Serialization is generally used in the following scenarios: 1. Permanently Save the object and save the object's byte sequence to a local file; 2. Passing objects in the network by serializing objects; 3. objects are passed between processes through serialization. The class to which the object belongs must be serializable or externalizable to be serialized. For classes that implement the serializable interface, the serialization and deserialization adopt the default serialization method. The externalizable interface inherits the serializable interface and is an extension of the serializable interface, the class implementing the externalizable interface completely controls serialization and deserialization. Java. Io. objectoutputstream represents the object output stream. Its method writeobject (Object OBJ) can serialize the object and write the obtained byte sequence to the target output stream. Java. Io. objectinputstream indicates the object input stream. Its readobject () method can read the byte sequence from the source input stream, deserialize it into an object, and return it. 2 serialization Methods Assume that a customer class is defined. There may be several serialization methods as follows: 2.1 implement serializable. The readobject and writeobject methods are not defined. Objectoutputstream uses JDK to serialize non-transient instance variables of the customer object by default; Objectinputstream uses JDK to deserialize non-transient instance variables of the customer object by default. 2.2 implement serializable and define the readobject and writeobject Methods Objectoutputstream calls the writeobject (objectoutputstream out) method of the customer class to serialize non-transient instance variables of the customer object; Objectinputstream calls the readobject (objectinputstream in) method of the customer class to deserialize non-transient instance variables of the customer object.
2.3 implement externalizable and define the readexternal and writeexternal Methods Objectoutputstream calls the writeexternal method of the customer class to serialize non-transient instance variables of the customer object; Objectinputstream first instantiates an object using the non-parameter constructor of the customer class, and then deserializes the non-transient instance variables of the customer object using the readexternal method.
3 serializable Interface Class to enable its serialization function by implementing the java. Io. serializable interface. Classes that do not implement this interface cannot be serialized or deserialized in any State. All sub-types of serializable classes are themselves serializable. The serialization interface has no methods or fields and is only used to identify the serializable semantics. During deserialization, fields of the non-serializable class will be initialized using the public or protected non-parameter constructor of this class. The serializable subclass must be able to access the non-parameter constructor. The field of the serializable subclass will be restored from the stream. When traversing a Class View, you may encounter objects that do not support the serializable interface. In this case, notserializableexception will be thrown and classes that identify non-serializable objects will be thrown.
3.1 accurate signature Classes that require special processing during serialization and deserialization must use the following accurate signatures to implement special methods: Private void writeobject (Java. Io. objectoutputstream out) throws ioexception Private void readobject (Java. Io. objectinputstream in) throws ioexception, classnotfoundexception; Private void readobjectnodata () throws objectstreamexception; The writeobject method is used to write the state of the object of a specific class so that the corresponding readobject method can restore it. You can call out. defaultwriteobject to call the default mechanism for saving the fields of the object. This method does not need to involve the status of its superclass or subclasses. You can write fields to objectoutputstream by using the writeobject method or the method supported by dataoutput for basic data types. The status can be saved. The readobject method reads and restores class fields from the stream. It can call in. defaultreadobject to call the default mechanism to restore non-static and non-transient fields of the object. The defaultreadobject method uses the information in the stream to allocate the fields of the object saved by the corresponding specified field in the current object in the stream. This is used to process the situation where new fields need to be added after class evolution. This method does not need to involve the status of its superclass or subclasses. You can write fields to objectoutputstream by using the writeobject method or the method supported by dataoutput for basic data types. The status can be saved. The readobjectnodata method initializes the object status of a specific class without listing a given class as the superclass of the deserialized object. This occurs when the version of the deserialization instance class used by the receiver is different from that of the sender, and the class of the receiver version extension is not the class of the sender version extension. This happens when the serialized stream has been tampered with. Therefore, the readobjectnodata method can be used to correctly initialize the deserialized object, regardless of whether the source stream is "hostile" or incomplete. When writing an object to a stream, you must specify the serializable class of the alternative object to be used. Use an accurate signature to implement this special method: Any-access-modifier object writereplace () throws objectstreamexception; This writereplace method will be called by serialization, provided that this method exists and can be accessed through a method defined in the class of the serialized object. Therefore, this method can have private, protected, and package-Private access. The subclass follows the Java access rules for this method. When reading an instance of a class from a stream, you must specify the correct signature for the substitute Class to implement this special method. Any-access-modifier object readresolve () throws objectstreamexception; This readresolve method follows the same calling rules and access rules as writereplace. If a class defines the readresolve method, the readresolve method will be called at the end of deserialization. The object returned by this method is the final result of deserialization. 3.2 serialversionuid During serialization, a version number called serialversionuid is used to associate with each serializable class, in the deserialization process, this serial number is used to verify whether the sender and receiver of the serialized object have loaded classes compatible with serialization for this object. If the serialversionuid of the class loaded by the receiver is different from the version of the class of the corresponding sender, deserialization will lead to invalidclassexception. The serializable class can explicitly declare its own Serialversionuid: Any-access-modifier static final long serialversionuid = 42l; If the serialversionuid is not explicitly declared for the serializable class, the default serialversionuid value of the class is calculated based on all aspects of the class during the serialization runtime, as described in "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 the class details, which may vary according to compiler implementations, in this way, unexpected invalidclassexception may occur during deserialization. Therefore, to ensure the serialversionuid The serialization class must declare a clear serialversionuid value for consistency across different Java compilers. We strongly recommend that you use the private modifier to display the Declaration serialversionuid (if possible), because this declaration is only applicable to the direct Declaration class -- serialversionuid field as an inherited member. The array class cannot declare a clear serialversionuid, so they always have the default calculated value, but the array class does not match the serialversionuid value.
4 externalizable Interface Externalizable is an extension of serailizable. Its serialization feature is as follows: Call the class method writeexternal during serialization, and call the readexternal Method for deserialization; When deserialization is performed, the non-parameter constructor of the class is called first, which is different from the default deserialization. Therefore, for classes that implement the externalizable interface to achieve serialization, A public non-parameter constructor must be provided. Otherwise, an exception will occur during deserialization. 5. Summary If the default serialization method is used, the instance can be serialized as long as a class implements the serializable interface. Generally, classes designed specifically for inheritance should try not to implement the serializable interface, because once the parent class implements the serializable interface, all its subclasses are also serializable. Disadvantages of the default serialization method: 1. It is not safe to serialize sensitive data that is not suitable for external disclosure of objects directly; 2. The system does not check whether the object's member variables meet the correct constraints. data may be transferred and modified, leading to running exceptions; 3. Recursive traversal of the object graph is required. If the object graph is very complex, it will consume a lot of resources and cause stack overflow of the Java Virtual Machine; 4. Make the class interface restricted by the internal implementation of the class, and restrict the upgrade and maintenance of the class. Implement the private writeobject () and readobject () of the serializable interface, or implement the externalizable interface, and implement the writeexternal () and readexternal () methods, the public-type non-parameter constructor is provided to control the serialization process, which can effectively avoid the shortcomings of the default serialization method. |