Java serialization, java serialization, and deserialization
1. Overview through the serialization mechanism, we can convert objects in Java memory into binary byte streams, so that we can store Java objects to disks or transmit Java objects over the network.
1.1 serialization meaning and meaning serialization mechanism allows you to convert serialized Java objects into byte sequences, which can be stored on disks or transmitted over the network, in case that the original object will be restored later. The serialization mechanism allows objects to exist independently from program running.
Object serialization (Serilize) refers to writing a Java object into the IO stream. In contrast, the object deserialization (Deserialize) refers to recovering the Java object from the IO stream.
To enable an object to support serialization, you must enable its class to implement one of the following two interfaces:
Seriliazable
Externalizable
Classes of all objects transmitted over the network should be serializable, such as parameters and return values during RMI (remote method call.
All classes of objects to be stored on the disk must be serializable. For example, applications in the Web application must be saved to the HttpSession or SevletContext attribute.
2. Use object stream for serialization
Import java. io. fileInputStream; import java. io. fileNotFoundException; import java. io. fileOutputStream; import java. io. IOException; import java. io. objectInputStream; import java. io. objectOutputStream; import java. io. serializable; public class SerializeTest {public static void main (String [] args) {try {ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("src/com/t/color.txt ")); color color = new Color ("Red"); oos. writeObject (color); // write the object to the output stream} catch (FileNotFoundException e) {e. printStackTrace ();} catch (IOException e) {e. printStackTrace ();} try {ObjectInputStream ois = new ObjectInputStream (new FileInputStream ("src/com/t/color.txt ")); // read the object from the input stream and convert it to the Color class Color col = (Color) ois. readObject (); System. out. println (col. getColor ();} catch (FileNotFoundException e) {e. printStackTrace ();} catch (IOException e) {e. printStackTrace ();} catch (ClassNotFoundException e) {e. printStackTrace () ;}} class Color implements Serializable {private static final long serialVersionUID =-3398911857061187891L; private String color; public Color (String color) {this. color = color;} public String getColor () {return color;} public void setColor (String color) {this. color = color ;}}
PS: deserialization does not require the constructor to initialize Java objects.
If multiple Java objects are written to a file using the serialization mechanism, the object must be read in the actual writing order when the deserialization mechanism is used to restore the object.
3. object Reference serialization if a member variable in a class has a reference type (not a basic type or a String type), the reference type must be serializable; otherwise, the class cannot be serialized, even if it implements Seriliazable or Externalizable, it cannot be serialized.
Import java. io. fileInputStream; import java. io. fileNotFoundException; import java. io. fileOutputStream; import java. io. IOException; import java. io. objectInputStream; import java. io. objectOutputStream; import java. io. serializable; public class SerializeTest {public static void main (String [] args) {try {ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("src/com/t/color.txt ")); color color = new Color ("Red"); Person person = new Person ("lavor_zl", color); oos. writeObject (color); // write the object to the output stream oos. writeObject (person); // write the object to the output stream} catch (FileNotFoundException e) {e. printStackTrace ();} catch (IOException e) {e. printStackTrace ();} try {ObjectInputStream ois = new ObjectInputStream (new FileInputStream ("src/com/t/color.txt ")); // read the object from the input stream and convert it to the Color class Color col = (Color) ois. readObject (); System. out. println (col. getColor (); Person per = (Person) ois. readObject (); System. out. println (per. getName ();} catch (FileNotFoundException e) {e. printStackTrace ();} catch (IOException e) {e. printStackTrace ();} catch (ClassNotFoundException e) {e. printStackTrace () ;}} class Color implements Serializable {/*****/private static final long serialVersionUID =-3398911857061187891L; private String color; public Color (String color) {this. color = color;} public String getColor () {return color;} public void setColor (String color) {this. color = color ;}} class Person implements Serializable {/***/private static final long serialVersionUID = 3426878037487779564L; private String name; private Color color; public Person (String name, color color) {this. name = name; this. color = color;} public String getName () {return name;} public void setName (String name) {this. name = name;} public Color getColor () {return color;} public void setColor (Color color) {this. color = color ;}}
Color color = new Color ("Red ");
Person person = new Person ("lavor_zl", color );
Oos. writeObject (color); // write the object to the output stream
Oos. writeObject (person); // write the object to the output stream
In general, the sequence of serialization is to serialize the color object first. When the person object is serialized and the Color object referenced by the person object is serialized again, however, the Color class Object referenced by the person object is a color object that has been serialized previously. The situation is different.
So what are the serialization rules used by the Java serialization mechanism?
1. All objects saved to the disk have a serialization number.
2. When the program tries to serialize an object, the program will check whether the object has been serialized. Only when the object has never been serialized in this virtual machine, the system will convert the object into a byte sequence and output it.
3. If each object has been serialized, the program simply outputs a serial number instead of re-serializing the object.
Based on these rules, when an object is serialized multiple times, the Java object will be converted into a byte sequence output only during the first serialization, even if the member variables of the object are changed later, the value of the member variable changed during deserialization is not output.
4. Custom serialization when we serialize an object, if you do not want to serialize a member variable of the object, you can use the transient keyword to modify the member variable. The transient keyword can only modify the member variable. Member variables modified with the transient keyword will be completely isolated from the serialization mechanism. In this way, the value of this variable cannot be obtained when the deserialization recovers a Java object. Java also provides a custom serialization mechanism that allows the program to control how to serialize each member variable through custom serialization, some member variables are not serialized at all (the same effect as those using the transient keyword ).
4.1 custom serialization Mechanism
The following special signature methods must be provided for classes that require special processing during serialization and deserialization. These special signature methods are used for custom serialization.
Private void writeObject (java. io. ObjectOutputStream out) throws IOException
Private void readObject (java. io. ObjectInputStream in) throws IOException, ClassNotFoundException
Private void readObjectNoData () throws ObjectStreamException
Import java. io. IOException; import java. io. objectInputStream; import java. io. objectOutputStream; import java. io. serializable; public class Test implements Serializable {private static final long serialVersionUID = 6102026641912972144L; private int id; private String name; public Test (int id, String name) {this. id = id; this. name = name;} private void writeObject (ObjectOutputStream out) throws IOException {out. writeInt (id); out. writeChars (name);} private void readObject (ObjectInputStream in) throws IOException, ClassNotFoundException {this. id = in. readInt (); // this. name = in. readLine () is acceptable, but this is not recommended for readLine. name = (String) in. readObject ();} public int getId () {return id;} public void setId (int id) {this. id = id;} public String getName () {return name;} public void setName (String name) {this. name = name ;}}
PS: the order in which the readObject () method reads the member variables should be the same as that in which the writeObject () stores the dust member variables; otherwise, the Java object cannot be restored normally.
Member variables modified by the static keyword cannot be serialized because they belong to the class rather than the object.
There is also a more thorough custom serialization mechanism, which can even replace the object with other objects when serializing the object. You can use the following method to implement
ANY-ACCESS-MODIFIER Object writeReplace () throws ObjectStreamException
This method has a serialization mechanism called before serialization, as long as the method exists.
Import java. io. fileInputStream; import java. io. fileOutputStream; import java. io. objectInputStream; import java. io. objectOutputStream; import java. io. objectStreamException; import java. io. serializable; import java. util. arrayList; public class Test implements Serializable {private int id; private String name; public Test (int id, String name) {this. id = id; this. name = name;} // rewrite the writeReplace () method. The program calls this method before serializing the Class Object. private Object writeReplace () throws ObjectStreamException {ArrayList <Object> list = new ArrayList <Object> (); list. add (id); list. add (name); return list;} public static void main (String [] args) {try {ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("replace.txt ")); objectInputStream ois = new ObjectInputStream (new FileInputStream ("replace.txt"); Test test = new Test (1, "lavor_zl"); oos. writeObject (test); ArrayList <Object> list = (ArrayList <Object>) ois. readObject (); System. out. println (list); // output: [1, lavor_zl]} catch (Exception e) {e. printStackTrace () ;}} public int getId () {return id;} public void setId (int id) {this. id = id;} public String getName () {return name;} public void setName (String name) {this. name = name ;}}
Compared with writeReplace (), the serialization mechanism also has a special method, which can implement protective replication of the entire object.
ANY-ACCESS-MODIFIER Object readResolve () throws ObjectStreamException
This method is called after the readObject () method. The returned value of this method replaces the original deserialization object.
The readResolve () method is particularly useful when serializing Singleton classes and enumeration classes.
4.1 another custom serialization mechanism Java also provides another custom serialization mechanism, which is entirely determined by the programmer to store and restore object data. To achieve this goal, the Java class must implement the Externalizable interface.
Void writeExternal (ObjectOutput out): class to be serialized to save the object state.
Void readExternal (ObjectInput in): This method is used to implement deserialization of classes to be serialized.