1. What is the serialization of Java objects
The Java platform allows us to create reusable Java objects in memory, but in general, these objects can exist only when the JVM is running, that is, they will not have a longer life cycle than the JVM. In a real-world application, however, it is possible to require that the specified object be saved (persisted) after the JVM has stopped running, and that the saved object will be re-read in the future. The serialization of Java objects can help us implement this functionality.
Using Java object serialization, when you save an object, it saves its state as a set of bytes, and in the future, these bytes are assembled into objects. It is important to note that object serialization holds the "state" of the object, which is its member variable. it is to be concluded that object serialization does not focus on static variables in the class.
In addition to using object serialization when persisting objects, object serialization is used when RMI (remote method calls) is used, or when objects are passed through the network. The Java Serialization API provides a standard mechanism for handling object serialization. In Java, as long as a class implements the Java.io.Serializable interface, it can be serialized.
Methods of serialization in 2.JDK
2.1 Example of serialization
Implement the Java.io.Serializable or Externalizable interface, which inherits the former, declares that it does not use the system's default serialization method, and the programmer writes the serialization method himself.
Public classsimpleserial { Public Static voidMain (string[] args)throwsException {File file=NewFile ("Person.out"); ObjectOutputStream oout=NewObjectOutputStream (Newfileoutputstream (file)); Person Person=NewPerson ("John", 101, Gender.male); Oout.writeobject (person); Oout.close (); ObjectInputStream oin=NewObjectInputStream (Newfileinputstream (file)); Object Newperson= Oin.readobject ();//no cast to person typeOin.close (); System.out.println (Newperson); }}
When the saved person object is re-read, there is no constructor that calls the person, and it appears as if the person object was restored directly using bytes.
When the person object is saved to the Person.out file, we can read the file elsewhere to restore the object, but you must ensure that the classpath of the reader contains Person.class ( Even if the person class is not displayed when reading the person object, as in the example above, ClassNotFoundException will be thrown.
2.2 Serialization ID Issues
Whether the virtual machine allows deserialization depends not only on the class path and function code consistency, but also on whether the serialization IDs of the two classes are consistent (that is, private static final long Serialversionuid = 1L). If you do not specify a serialization, the Id,java will automatically generate a default ID for the class with the Fingerprint Digest algorithm, the serialization ID will automatically change when you add a modified field to the classes, the class that precedes the deserialization fails, the package serializes a different ID error, so you must specify the serialization ID as needed, and if the ID is not changed, If the class field has added changes and so on, it is still compatible with the file before deserialization, and conversely does not want to be compatible before, the ID can be set to different.
The role of 2.3Serializable
Why does a class implement the Serializable interface and it can be serialized? After the generic class inherits the interface, the ObjectOutputStream can be used to persist the object, otherwise the tune will not be able to writeObject0 the exception when the sequence is called.
Private voidWriteObject0 (Object obj,Booleanunshared)throwsIOException {if(objinstanceofString) {writestring (String) obj, unshared); } Else if(Cl.isarray ()) {Writearray (obj, desc, unshared); } Else if(objinstanceofEnum) {writeenum (Enum) obj, desc, unshared); } Else if(objinstanceofSerializable) {writeordinaryobject (obj, desc, unshared); } Else { if(extendeddebuginfo) {Throw NewNotserializableexception (Cl.getname () + "\ n" +debuginfostack.tostring ()); } Else { Throw Newnotserializableexception (Cl.getname ()); } } }
From the code above, if the type of the object being written is a string, or an array, or an enum, or serializable, then the object can be serialized, or notserializableexception will be thrown.
If you just let a class implement the Serializable interface without any other processing, you would use the default serialization mechanism. Using the default mechanism, when serializing an object, it not only serializes the current object itself, but also serializes other objects referenced by the object, as well as other objects referenced by those other objects, and so on. Therefore, if an object contains member variables that are container class objects, and the containers contain elements that are also container class objects, the serialization process is more complex and expensive.
2.4 Ways to influence serialization
In real-world applications, the default serialization mechanism cannot be used in some cases. For example, you want to ignore sensitive data during serialization, or simplify the serialization process.
(1) Transient keywords
When a field is declared as transient, the default serialization mechanism ignores the field. The age field in the person class is declared here as transient
(2)WriteObject () method and ReadObject () method
For the above field that has been declared as transitive, is there any other way to make it serializable again, in addition to removing the transitive keyword? One way to do this is to add two methods to the person class: WriteObject () and ReadObject () as follows:
Public classPersonImplementsSerializable {transient PrivateInteger age =NULL; Private voidWriteObject (ObjectOutputStream out)throwsIOException {out.defaultwriteobject (); Out.writeint (age); } Private voidReadObject (ObjectInputStream in)throwsIOException, ClassNotFoundException {in.defaultreadobject (); Age=In.readint (); }}
The Defaultwriteobject () method in ObjectOutputStream is called first in the WriteObject () method, which executes the default serialization mechanism, ignoring the age field. The Writeint () method is then called to display the age field to the ObjectOutputStream. The function of ReadObject () is to read the object, and its principle is the same as the WriteObject () method. It is important to note that writeobject () and ReadObject () are private methods, which are writeserialdata methods in the ObjectOutputStream, And the Readserialdata in ObjectInputStream are called with reflection.
(3) Externalizable interface
Either using the Transient keyword or using the writeobject () and ReadObject () methods are all based on the serialization of the Serializable interface. Another serialization interface,--externalizable, is provided in the JDK, after which the serialization mechanism based on the serializable interface is invalidated. Using Externalizable for serialization, when the object is read, the parameterless constructor of the serialized class is called to create a new object, and the values of the fields of the saved object are then populated into the new object. Therefore, the class that implements the Externalizable interface must provide an argument-free constructor, and its access rights are public. The serialized object is then overloaded with writeexternal () and the Readexternal () method to serialize the deserialization operation.
Public classPersonImplementsexternalizable {PrivateString name =NULL; transient PrivateInteger age =NULL; ... @Override Public voidWriteexternal (ObjectOutput out)throwsIOException {out.writeobject (name); Out.writeint (age); } @Override Public voidReadexternal (ObjectInput in)throwsIOException, classnotfoundexception {name=(String) in.readobject (); Age=In.readint (); } }
(4) Readresolve () method
When we use the singleton pattern, we should expect that an instance of a class should be unique, but if the class is serializable, you can add a readresolve () method to the person class in order to be able to maintain the characteristics of the singleton in the serialization process. The singleton object is returned directly in the method. Either implementing the Serializable interface or the Externalizable interface, the Readresolve () method is called when the object is read from the I/O stream. The object that was created in the deserialization process is replaced directly with the object returned in Readresolve (), and the object being created is garbage collected.
Public classPersonImplementsSerializable {Private Static classInstanceholder {Private Static FinalPerson instatnce =NewPerson ("John", 31, Gender.male); } Public StaticPerson getinstance () {returninstanceholder.instatnce; } ...PrivateObject Readresolve ()throwsobjectstreamexception {returninstanceholder.instatnce; } }
3. Precautions
A) When a parent class is serialized and the subclass is automatically serialized, no explicit implementation of the serializable interface is required;
b) When an instance variable of an object refers to another object, the object is serialized by serializing it;
c) Not all objects can be serialized, and there are a number of reasons why not, such as:
1. Security reasons, such as an object has Private,public and other fields, for a transmission of the object, such as writing to a file, or RMI transmission, etc., during the serialization of the transfer process, the object's private domain is not protected.
2. Resource allocation reasons, such as the Socket,thread class, can be serialized, transmitted or saved, and cannot be re-allocated, and it is not necessary to implement
Turn an object into a byte sequence for easy transmission.
Understanding the serialization of Java objects
Object serialization of the Java Foundation