1. function and use of serialization
Serialization: The process of converting an object to a sequence of bytes is called serialization of an object .
Deserialization: The process of reverting a sequence of bytes to an object is called deserialization of the object .
There are two main uses for serialization of objects:
1) The object's byte sequence is permanently saved to the hard disk, usually stored in a file;
2) A sequence of bytes that transmits an object over the network.
2. Steps for serialization
Java.io.ObjectOutputStream represents an object output stream, and its writeobject (object obj) method serializes the Obj object specified by the parameter and writes the resulting sequence of bytes to a target output stream.
Java.io.ObjectInputStream represents an object input stream, and its readobject () method reads a sequence of bytes 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, and the class that implements the Externalizable interface controls the serialization behavior entirely by itself, whereas classes that implement the serializable interface can take the default serialization method.
Object serialization consists of the following steps:
1) Create an object output stream, which can wrap a different type of target output stream, such as a file output stream;
2) writes an object through the WriteObject () method of the object output stream.
The steps for deserializing an object are as follows:
1) Create an object input stream, which can wrap a different type of source input stream, such as a file input stream;
2) The object is read through the ReadObject () method of the object input stream.
3. Default serialization
Serialization only needs to implement the Java.io.Serializable interface. There is a serialversionuid parameter when serializing, and theJava serialization mechanism verifies version consistency by judging the serialversionuid of the class at run time . In the case of deserialization, the Java virtual Opportunity compares the Serialversionuid in the stream of bytes passed to the serialversionuid of the local corresponding entity class, and if the same entity class is considered consistent, it can be deserialized, Otherwise, the Java virtual Opportunity refuses to deserialize the entity class and throws an exception. There are two ways to build Serialversionuid:
1, the default 1L
2. Generate a 64-bit hash field based on class name, interface name, member method, and attributes.
If an entity class that implements the Java.io.Serializable interface does not explicitly define a variable named Serialversionuid, which is of type long, The Java serialization mechanism automatically generates a SERIALVERSIONUID based on the compiled. class file, and if the. class file does not change, then the serialversionuid will not change even if it is compiled more than once. In other words,Java defines the default serialization, deserialization method for the user, is actually the Defaultwriteobject method of ObjectOutputStream and the Defaultreadobject method of ObjectInputStream . See an example:
1 public class Serializableobject implements Serializable 2 {3 private static final long serialversionuid = 1L; 4
5 private string str0; 6 private transient string str1; 7 private static string str2 = "abc"; 8 9 Pub Lic Serializableobject (String str0, String str1) { this.str0 = str0;12 this.str1 = str1;13}14 public String GetStr0 () () () ()- { str0;18 -}19- getStr1 () 21 { return str1;23 }24}
1 public static void main (string[] args) throws Exception 2 {3 file File = new file ("D:" + file.separator + "S.txt"); 4 outputstream os = new FileOutputStream (file); 5 ObjectOutputStream oos = new ObjectOutputStream (OS), 6 oos.writeobject (New Serializableobject ("Str0", "str1 ")); 7 Oos.close (); 8 9 InputStream is = new FileInputStream (file); ObjectInputStream ois = new ObjectInputStream (IS), serializableobject so = (serializableobject) ois.readobject (); System.out.println ("STR0 =" + SO.GETSTR0 ()); System.out.println ("str1 =" + SO.GETSTR1 ()); Ois.close (); 15}
Do not run first, use a binary viewer to view the S.txt file, and explain the contents of each section in detail.
The 1th part is the serialized file header
◇ac ed:stream_magic Serialization Protocol
◇00 05:stream_version Serialization Protocol version
◇73:tc_object declares this to be a new object
The 2nd part is the description of the class to serialize, here is the Serializableobject class
◇72:tc_classdesc statement here begins a new class
◇00 1F: Decimal 31, which indicates that the length of the class name is 31 bytes
◇63 6F 6D ... 65 63 74: means "com.xrq.test.SerializableObject" this string of characters, you can count it is really 31 bytes
◇00 xx 01:serialversion, serialized id,1
◇02: Tag number that declares that the object supports serialization
◇00 01: The class contains 1 of the total number of domains
The 3rd part is the description of each property item in the object
◇4C: The character "L", which indicates that the property is an object type and not a basic type
◇00 04: Decimal 4, indicating the length of the property name
◇73 74 72 30: string "STR0", property name
◇74:tc_string, representing a new string, referencing the object with a string
Part 4 is the information of the parent class of the object, without which the parent class does not have this part. It's like the 2nd part of the parent class.
◇00 12: Decimal 18, indicating the length of the parent class
◇4C 6A 61 ... 6E 3 B: "l/java/lang/string;" Represents the parent class property
◇78:tc_endblockdata, object block end flag
◇70:tc_null, stating that there are no other super-class flags
The 5th part is the actual value of the property item of the output object, and if the property item is an object, the object is also serialized here, as in the 2nd part of the rule.
◇00 04: Decimal 4, length of the attribute
◇73 74 72 30: string "STR0", Str0 property value
From the above for the parsing of the serialized binary file, we can draw the following key conclusions:
1. The class information is saved after serialization
2. Attributes declared as transient will not be serialized, which is the function of the transient keyword
3. The property declared as static will not be serialized, as the problem can be understood, the serialization holds the state of the object, but the static modified variable belongs to the class and not to the variable, so serialization does not serialize it
Next run the code above to see
STR0 = STR0STR1 = null
Because STR1 is a variable of type transient, it is not serialized, so the deserialization is not anything, and the null displayed is consistent with our conclusion.
4.defaultwriteobject and Defaultreadobject (manually specify serialization)
4.1 Specifying serialization manually
Java does not force the user to use the default serialization method, the user can also according to their own preferences to specify their own desired serialization----as long as you can ensure that the serialization of the data before and after the need to be able to. The rules for manually specifying serialization methods are:
When serializing and deserializing, the virtual opportunity first attempts to invoke the WriteObject and ReadObject methods in the object, making the user-defined serialization and deserialization. If there is no such method, then the default call is ObjectOutputStream's Defaultwriteobject and ObjectInputStream's Defaultreadobject method. In other words, using the custom WriteObject method and the ReadObject method, users can control the process of serialization and deserialization themselves.
This is very useful. Like what:
1, some scenes, some fields we do not want to use Java to provide us with the serialization method, but want to be in a custom way to serialize it, such as ArrayList Elementdata, HashMap table (as to why the reason is explained when you write these two classes later), you can serialize them by declaring them as transient and then using the way you want them in WriteObject and ReadObject.
2, because the serialization is not safe, so some scenarios we need to encrypt some sensitive fields and then serialize, and then deserialize the same way to decrypt, to a certain extent, to ensure the security. To do this, you have to write your own writeobject and Readobject,writeobject methods to encrypt fields before serialization, ReadObject method decrypts the field after serialization
The above example serializobject this class, and the main function does not need to be modified:
1 public class Serializableobject implements Serializable 2 {3 private static final long serialversionuid = 1L; 4 5 Private String Str0; 6 private transient String str1; 7 private static String STR2 = "abc"; 8 9 Public Serializableobject (String str0, String str1) {this.str0 = str0;12 this.str1 = Str1;13}14-public string GetStr0 () () ()-{-Return str0;18}19-public string GetStr1 ( ) {return str1;23}24 private void WriteObject (Java.io.ObjectOutputStream s) throws Except ion26 {System.out.println ("I want to control the serialization process"), S.defaultwriteobject (); S.writeint (Str1.leng th ()); (int i = 0; i < str1.length (); i++) to S.writechar (Str1.charat (i)); 32}33 34 private void ReadObject (Java.io.ObjectInputStream s) throws Exception35 {System.out.println ("I want to control the deserialization "); PNs S.defaultreadobject ();int length = S.readint (); char[] cs = new char[length];40 for (int i = 0; i < length; i++) Cs[i] = S.readchar (); str1 = new String (cs, 0, length); 43}44}
Look directly at the results of the operation:
I want to control the serialization process myself I want to control the process of deserialization STR0 = STR0STR1 = str1
See, the program went to our own written writeobject and ReadObject, and the transient modified STR1 also successfully serialized, deserialized----because the STR1 was written to the file and read from the file. Look again at the binary of the S.txt file:
See the orange part of the WriteObject method added str1 content. Now, summarize the usual usage of writeobject and readobject:
The object is serialized, deserialized, and then appended to the end of the file by the Defaultwriteobject and Defaultreadobject methods, and the additional content that needs to be read is read from the end of the file.
4.2 To achieve the purpose of serializing static and transient variables in this way
1/** 2 * Serialized DEMO Test Program 3 * 4 * @author Skywang 5 */6 7 import Java.io.FileInputStream; 8 Import Java.io.FileOutputStream; 9 Import Java.io.ObjectInputStream; Ten import Java.io.ObjectOutputStream; Import java.io.Serializable; Import java.io.IOException; Import java.lang.ClassNotFoundException; public class SerialTest5 {private static final String Tmp_file = ". Serialtest5.txt"; static void Main (string[] args) {19//"Object" is saved by serialization of Testwrite (); 21//The serialized "Object" is read 22 Testread (); 23} 24 25 26/** 27 * The Box object is serialized and saved to a file. */private static void Testwrite () {30 try {31//Gets the object output stream corresponding to the file tmp_file. In ObjectOutputStream, you can write only "basic data" or "objects that support serialization" objectoutputstream out = new ObjectOutputStream (New FileOutputStream (Tmp_file)); 35//Create Box object, box implements serializable serialization interface 36 Box box = new box ("desk", 80, 48); 37//Writes the box object to the object output stream out, which is equivalent to saving the object to a file Tmp_file out.writeobject (box); 39//print "box object" System.out.println ("testwrite Box:" + box); 41//Modify box value of box = new Box ("Guest", 100, 50); Out.close (); * catch (Exception ex) {ex.printstacktrace (); 47} 48} 49 50/** 51 * FROM Read out the "serialized box object" in the file "* * * */" private static void Testread () {55//Get file Tmp_file corresponding object output Inflow. ObjectInputStream in = new ObjectInputStream (new FileInputStream (Tmp_file)); 58//From the object input stream, read the previously saved box object. Box box = (box) in.readobject (); 60//print "box object" System.out.println ("testread Box:" + box); In.close (); (Exception e) {e.printstacktrace (); 65} 66} 67} The/** * Box class "supports serialization". Because box implements the serializable interface. 72 * 73 * In fact, a class needs to implement serializable for serialization without implementing any functions. * * * * implements Serializable {private static int width; transient-private int height; The private String name; N-A public Box (String name, int width, int height) {Bayi this.name = name; this.width = width; 83 This.height = height; WriteObject (ObjectOutputStream out) throws ioexception{Out.defaultwriteobjec t ();//enable the custom WriteObject () method to take advantage of the logic built into the automatic serialization. Out.writeint (height); Out.writeint (width); //system.out.println ("Box--writeobject width=" +width+ ", height=" +height); ReadObject (ObjectInputStream in) throws ioexception,classnotfoundexception{94 I N.defaultreadobject ();//defaultreadobject () supplemental automatic serialization of the height = In.readint (); width = In.readint (); //system.oUt.println ("Box---readobject width=" +width+ ", height=" +height "); 98} @Override101 Public String toString () {102 return "[" +name+ ": (" +width+ "," +height+ ")]"; 1 03}104}
Operation result :
Testwrite box: [Desk: (+)]testread box: [Desk: (80, 48)]
Program Description :
"Serialization does not automatically save static and transient variables", so to save them, we need to read and write manually through WriteObject () and ReadObject ().
(01) Write the variable you want to save by using the WriteObject () method. The original definition of writeobject is in Objectoutputstream.java, which we can overwrite with the following example:
private void WriteObject (ObjectOutputStream out) throws ioexception{ out.defaultwriteobject ();//Make Custom WriteObject The () method can take advantage of the logic built into the automatic serialization. Out.writeint (ival); To save the value of type int, use Writeint () out.writeobject (obj); To save "object", use WriteObject ()}
(02) through the ReadObject () method, read the previously saved variables. The original definition of ReadObject is in Objectinputstream.java, which we can overwrite with the following example:
private void ReadObject (ObjectInputStream in) throws ioexception,classnotfoundexception{ In.defaultreadobject () ; Enables the custom ReadObject () method to take advantage of the logic built into the automatic serialization. int ival = In.readint (); To read "value of type int", use Readint () Object obj = In.readobject ();//To read "object", use ReadObject ()}
So far, we've covered the serialization of handling static and transient variables.
5.Externalizable
If a class is fully responsible for its own serialization, implement the Externalizable interface instead of the serializable interface.
Externalizable: He is a subclass of the serializable interface, sometimes we do not want to serialize so much, you can use this interface, the Writeexternal () and Readexternal () methods of this interface can specify which properties to serialize.
It is important to note that declaring a class to implement the Externalizable interface has a significant security risk. The Writeexternal () and Readexternal () methods are declared public, and malicious classes can use these methods to read and write object data. If the object contains sensitive information, take extra care.
/** * Serialized DEMO Test program * * @author Skywang */import java.io.FileInputStream; Import Java.io.FileOutputStream; Import Java.io.ObjectInputStream; Import Java.io.ObjectOutputStream; Import Java.io.ObjectOutput; Import Java.io.ObjectInput; Import java.io.Serializable; Import java.io.Externalizable; Import java.io.IOException; Import java.lang.ClassNotFoundException; public class ExternalizableTest2 {private static final String Tmp_file = ". Externalizabletest2.txt"; public static void Main (string[] args) {//"object" is saved by serialization Testwrite (); The serialized "Object" is read out Testread (); /** * The Box object is serialized, saved to file */private static void Testwrite () {try {//Get file Tmp_file The corresponding object output stream. ObjectOutputStream, you can write only "basic data" or "objects that support serialization" objectoutputstream out = new ObjectOutputStream ( New FileOutputStream (Tmp_file)); Create box Object Box box = new box ("desk", 80, 48); Writes the box object to the object output stream out, which is equivalent to saving the object to the file Tmp_file out.writeobject (box); print "Box object" System.out.println ("testwrite Box:" + box); Out.close (); } catch (Exception ex) {ex.printstacktrace (); }}/** * read out "serialized box object" from File */private static void Testread () {try {//Get file Tmp_file The corresponding object input stream. ObjectInputStream in = new ObjectInputStream (new FileInputStream (Tmp_file)); From the object input stream, read the previously saved box object. Box box = (box) in.readobject (); print "Box object" System.out.println ("testread Box:" + box); In.close (); } catch (Exception e) {e.printstacktrace (); }}}/** * Box class implements Externalizable interface */class box implements externalizable {private int width; private int height; private String name; Public box () {} public box (String name, int width, int height) {this.name = name; This.width = width; This.height = height; } @Override public void writeexternal (ObjectOutput out) throws IOException {out.writeobject (name); Out.writeint (width); Out.writeint (height); } @Override public void Readexternal (ObjectInput in) throws IOException, classnotfoundexception {name = (Str ing) in.readobject (); width = In.readint (); Height = In.readint (); @Override public String toString () {return "[" +name+ ": (" +width+ "," +height+ ")]"; }}
Operation result :
Testwrite box: [Desk: ($)]testread box: [null: (0, 0)]
Precautions:
(01) The class that implements the Externalizable interface does not automatically save the data as if the serializable interface is implemented.
(02) The class that implements the Externalizable interface must implement the Writeexternal () and the readexternal () interface! Otherwise, the program will not compile properly!
(03) The class that implements the Externalizable interface must define a constructor without parameters! The constructor is called by default, otherwise the program will not compile properly!
The methods of Writeexternal () and readexternal () are public, not very safe!
6. Summary of complex serialization scenarios
Although the serialization of Java can guarantee the persistence of object state, it is difficult to deal with some complex object structures, and finally a summary of some complex object situations:
1, when the parent class inherits the serializable interface, all subclasses can be serialized
2, the subclass implements the Serializable interface, the parent class does not have, the attribute in the parent class cannot be serialized (no error, data loss), but the attribute in the subclass can still be serialized correctly
3, if the serialized property is an object, then this object must also implement the Serializable interface, otherwise it will error
4, when deserializing, if the object's properties are modified or truncated, then the modified part of the property will be lost, but will not error
5, when deserializing, if the Serialversionuid is modified, the deserialization will fail
Reprint: http://www.cnblogs.com/xrq730/p/4821958.html
Http://www.cnblogs.com/skywang12345/p/io_06.html
Java Object Representation 1: The role of serialization, deserialization