Detailed explanation of Java serializable and externalizable serialization and deserialization — to

1、 What is serialization? "Object serialization" has been a feature since Java 1.1. In short, it can convert an object (marking the type of object) and its state into bytecode, save it (it can be saved in database, memory, file, etc.), and then restore its state (that is, deserialization) at an appropriate time. Serialization can be done not only locally, but also through the network. It automatically shields operating system differences, byte order, etc. For example, an object is generated and serialized on the windows platform, and then transmitted to a UNIX machine through the network, You can then refactor correctly on this UNIX machine (deserialization) this object. You don't have to care about how data is represented on different machines, the order of bytes or any other details. In addition, you should also understand the following points: a. the java.io.serializable interface does not have any method property field, and the class implementing it only semantically indicates that it can be serialized. B. for a serializable (serializable) during the reassembly of the object, no Builder (even the default builder) will be called. The whole object is recovered by obtaining data from InputStream. C. If a class is serializable, its subclasses are also serializable.

2、 When is serialization used? It provides support for two main features of Java: remote method invocation (RMI): enables objects that originally exist in other machines to behave as if they were on the local machine. When sending messages to remote objects, it is necessary to transmit parameters and return values through object serialization. Object serialization is also necessary for Java beans. When a bean is used, its state information is usually configured during design. After the program is started, this state is changed The status information must be saved for recovery after the program is started; The specific work is completed by object serialization. Three serialization process Java io. Objectoutputstream represents the object output stream. Its writeobject (object obj) method can serialize the obj object specified by the parameter and write the resulting byte sequence to a target output stream.   java. io. Objectinputstream represents the object input stream. Its readObject () method reads byte sequences from a source input stream, deserializes them into an object, and returns them Only objects of classes that implement the serializable and externalizable interfaces can be serialized. The externalizable interface inherits from the serializable interface. The classes that implement the externalizable interface completely control the serialization behavior, while the classes that only implement the serializable interface can adopt the default serialization method. Object serialization includes the following steps: 1) create an object output stream, which can wrap another type of target output stream, such as file output stream; 2) write the object through the writeobject () method of the object output stream. The steps of object deserialization are as follows: 1) create an object input stream, which can wrap another type of source input stream, such as file input stream; 2) read the object through the readObject () method of the object input stream. Let's take a look at a corresponding example. The contents of the class are as follows:

The output results are as follows: obj1 = Hello! Obj2 = sat SEP 15 22:02:21 CST 2007 obj3 = name = amigo, age = 24 obj4 = 123

4、 How to serialize in Java? If you want to serialize or deserialize a class, you only need to implement Java io. Serializable interface. If classes do not implement this interface, their state cannot be serialized and deserialized in general. Note that I say "generally" here because Java also provides another interface java io. Externalizable. I will explain the use of this interface separately below. 1. When the transient keyword controls the serialization process, there may be a specific sub object that does not want Java's serialization mechanism to automatically save and recover. Generally, this situation occurs if the sub object contains sensitive information (such as password) that you do not want to serialize. Even if that information has "private" in the object (private) attribute, but once serialized, people can get it by reading a file or intercepting network transmission. One way to prevent the sensitive part of an object from being serialized is to implement its own class as externalizable. In this way, nothing can be serialized automatically, but in writeexternal() Explicitly serialize those parts that are needed. However, if you operate on a serializable object, all serialization operations are performed automatically. To solve this problem, You can use transient (temporarily) turn off serialization field by field. V. special case - the parent class is not serializable and the child class is serializable. We can see that for the attribute B1 of B, it can be serialized correctly, but for the attribute a inherited from a, B does not have the correct serialization. Why? We look at the above operation results and find that when deserializing, B implements Ser When serializable is used to deserialize, it does not call its own constructor, but when deserializing B, But called the constructor of its superclass (in fact, not only the constructor, all initialization processes of a will proceed normally). This is the reason why the values of a and B in the above results are not deserialized correctly. Therefore, for such a class whose parent class is not serialized but whose subclasses can be serialized, the subclasses should handle the public, protected, and friendly attributes of the superclass separately. VI. differences between serializable classes Serialization compatibility of versions all classes that implement the serializable interface have a static variable representing the serialization version identifier: private static final long serialVersionUID;

The above serialVersionUID values are automatically generated by the Java runtime environment according to the internal details of the class. If the source code of the class is modified and recompiled, the value of serialVersionUID of the newly generated class file may also change. The default value of the serialVersionUID of a class completely depends on the implementation of the java compiler. For the same class, compiling with different Java compilers may lead to different serialversionuids or the same. In order to improve the independence and certainty of serialVersionUID, it is strongly recommended to define serialVersionUID displayed in a serializable class and give it an explicit value. There are two purposes for explicitly defining serialVersionUID: 1) in some cases, you want different versions of a class to be compatible with serialization, so you need to ensure that different versions of a class have the same serialVersionUID; 2) in some cases, you do not want different versions of the class to be compatible with serialization, so you need to ensure that different versions of the class have different serialversionuids. 7、 As for writereplace () and readresolve (), for classes that implement the serializable or externalizable interface, the writereplace () method can make the object replace itself with an object before it is written to the stream. When serializing, the serializable class will write the object to the stream. If we want another object to replace the current object to write to the stream, we can implement the following method, and the signature of the method should be exactly the same: any-access-modifier object writereplace() throws objectstreamexception; The writeReplace () method is called before ObjectOutputStream is ready to write the object to the stream. ObjectOutputStream first checks whether the serialized class defines the writeReplace () method. If it is defined, it will be replaced by another object by calling it. The object returned by the method is either the same or compatible with the object type it replaces. Otherwise, ClassCastException will be thrown. Similarly, when deserializing, we need to read an object from the stream. If we want to replace the read object with another object instance, we need to implement a method that is completely consistent with the signature of the following method. ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException; The readresolve method is called when the object is read from the stream. Objectinputstream will check whether the deserialized object has defined this method. If so, the read object will return a substitute object. Like the writereplace () method, the returned object must be compatible with the object it replaces, otherwise ClassCastException will be thrown. If there are these methods in the serialized class, Then their execution order is as follows: a. writereplace() B. writeobject() C. readobject() D. readresolve(). The following is about readresolve() and writereplace() in the Java doc Serializable classes that need to design an alternative object to be used when writing an object to the stream should implement this special method with the exact signature:

ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException; This writeReplace method is invoked by serialization if the method exists and it would be accessible from a method defined within the class of the object being serialized. Thus,the method can have private,protected and package-private access. Subclass access to this method follows java accessibility rules.

Classes that need to designate a replacement when an instance of it is read from the stream should implement this special method with the exact signature. ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException; This readResolve method follows the same invocation rules and accessibility rules as writeReplace. VIII

In fact, this problem can be clarified by simply thinking about it. Methods are stateless, that is, some instructions. Instructions do not need to be serialized. As long as your JVM classloader can load this class, class method instructions can be obtained naturally. What serialization really needs to save is the value of the object attribute and the type of the object. These knowledge can be found in a book on basic Java programming or Java manual. I don't think we should make this basic conceptual mistake.

We can do a simple test to confirm:

<span style="color: #0000ff;">import<span style="color: #000000;"> java.io.Serializable; 

<span style="color: #0000ff;">public <span style="color: #0000ff;">class DomainObject <span style="color: #0000ff;">implements<span style="color: #000000;"> Serializable {

</span><span style="color: #0000ff;"&gt;private</span><span style="color: #000000;"&gt; String name; 

</span><span style="color: #0000ff;"&gt;private</span> <span style="color: #0000ff;"&gt;int</span><span style="color: #000000;"&gt; age ; 

</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;int</span><span style="color: #000000;"&gt; getAge(); { 
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; age; 
} 

</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span> setAge(<span style="color: #0000ff;"&gt;int</span><span style="color: #000000;"&gt; age); { 
    </span><span style="color: #0000ff;"&gt;this</span>.age =<span style="color: #000000;"&gt; age; 
} 

</span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; String getName(); { 
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; name; 
} 

</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; setName(String name); { 
    </span><span style="color: #0000ff;"&gt;this</span>.name =<span style="color: #000000;"&gt; name; 
} 

}

<span style="color: #0000ff;">package<span style="color: #000000;"> com.javaeye;

<span style="color: #0000ff;">import<span style="color: #000000;"> java.io.FileOutputStream;
<span style="color: #0000ff;">import<span style="color: #000000;"> java.io.ObjectOutputStream;

<span style="color: #0000ff;">public <span style="color: #0000ff;">class<span style="color: #000000;"> Main {

</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;static</span> <span style="color: #0000ff;"&gt;void</span> main(String[] args); <span style="color: #0000ff;"&gt;throws</span><span style="color: #000000;"&gt; Exception { 
    DomainObject obj </span>= <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; DomainObject();; 
    obj.setAge(</span>29<span style="color: #000000;"&gt;);; 
    obj.setName(</span>"fankai"<span style="color: #000000;"&gt;);; 
    FileOutputStream fos </span>= <span style="color: #0000ff;"&gt;new</span> FileOutputStream("DomainObject"<span style="color: #000000;"&gt;);; 
    ObjectOutputStream oos </span>= <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; ObjectOutputStream(fos);; 
    oos.writeObject(obj);; 
    oos.close();; 
    fos.close();; 
} 

}

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>