List of articles
- Preface
- One 、 Why serialize
- Two 、 First look at one Demo
- 3、 … and 、 Serialized ID
- Four 、 Parent child class serialization
- 5、 … and 、 Custom Serialization
- 6、 … and 、 Storage of multi object serialization
-
- 6.1 Write the same object of the same class multiple times
- 6.2 Write the same object of the same class multiple times ( Modify the attributes one by one )
- 6.3 Write different objects of the same class multiple times
- 6.4 Write different objects several times
- Java Serialization knowledge summary
Preface
When I was learning serialization a long time ago, I wrote an article about Java Serialized blog , But it’s just a simple use , Welcome to move :http://blog.beifengtz.com/article/36. I ran into a serialization problem at work last week , It is the problem of saving the value of parent-child class serialization , There’s a lot of detail about serialization , Let’s study this article carefully Java Serialization in .
One 、 Why serialize
Nowadays, most of the systems in enterprises are not written in single language , A platform may have Java、Python、Cpp、Lua Waiting for the language to be written , If there is data interaction within or between this platform and other platforms , There must be a unified data format , The data of each language must be sequenced into these unified formats before it can be recognized by other systems , The result of general serialization is a binary data , When the receiving system receives the binary data, it must be deserialized and converted into data that it can recognize . Except for network transmission, of course , Serialization is also a means of persistence , You can serialize it into a binary file for data storage . The common serialization formats supported by multiple languages are XML、JSON、ProtoBuf etc. .
Java There are also serialization methods supported by the language , In general, serialization is used in object persistence , Network transmission uses more of the three common serialization formats mentioned above .
Two 、 First look at one Demo
Serialized objects :
/**
* @author beifengtz
* <a href='http://www.beifengtz.com'>www.beifengtz.com</a>
* <p>location: serializ.javase_learning</p>
* Created in 10:41 2019/10/13
*/
public class User implements Serializable {
private static final long serialVersionUID = -6849794470754667710L;
private String name;
private transient String gender;
private int age;
private long regTime;
public User(String name, String gender, int age, long regTime) {
this.name = name;
this.gender = gender;
this.age = age;
this.regTime = regTime;
}
public User(String name, int age, long regTime) {
this.name = name;
this.age = age;
this.regTime = regTime;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", gender='" + gender + '\'' +
", age=" + age +
", regTime=" + regTime +
'}';
}
}
Serialization and deserialization :
/**
* @author beifengtz
* <a href='http://www.beifengtz.com'>www.beifengtz.com</a>
* <p>location: serialization.javase_learning</p>
* Created in 10:46 2019/10/13
*/
public class SerializationDemo {
public static void main(String[] args) {
User user = new User("beifengtz", " male ", 100, System.currentTimeMillis() / 1000);
System.out.println(" Before serialization :");
System.out.println(user);
// Serialize objects into files
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("serFile"));
oos.writeObject(user);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
assert oos != null;
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// Deserialize from a file to an object
File file = new File("serFile");
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream(file));
User serUser = (User) ois.readObject();
System.out.println(" After serialization :");
System.out.println(serUser);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
assert ois != null;
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
The result of the final console output :
Before serialization :
User{name='beifengtz', gender=' male ', age=100, regTime=1570935427}
After serialization :
User{name='beifengtz', gender='null', age=100, regTime=1570935427}
Then let’s look at the serialization file generated in the middle serFile
, Open it directly and it’s garbled , Open it with binary editor and it’s full of 16 Hexadecimal characters .
3、 … and 、 Serialized ID
Serializer and deserializer want a successful data transfer , Three conditions must be guaranteed :
- Class full path must be the same , For example, all of them are
com.beifengtz.User
- Class function code must be the same
- serialize ID It has to be the same , For example, all of them are
private static final long serialVersionUID = 1L
None of the above three conditions can be serialized successfully , If serialization is not defined ID The virtual opportunity randomly generates a ID, But this is not very controllable for the program , After all, serialization serves multiple ends . Here’s one IBM Developer An example from an article in , Use cases in practical application :
Facade In the pattern ,Facade Object Is to provide a unified access interface for applications , In the case procedure Client The client uses this mode , The structure of the case procedure is shown in the figure :
Client End pass Façade Object To interact with business logic objects . And on the client side Façade Object Not directly from Client Generate , But needs Server End generation , And then serialize the binary object data through the network to Client,Client Responsible for deserializing to get Façade object . This mode enables Client The use of the end program requires the permission of the server , meanwhile Client End and server end Façade Object Class needs to be consistent . When the server wants to make a version update , Just put the server-side Façade Object Serialization of classes ID Generate… Again , When Client End deserialization Façade Object Will fail , That is to say, compulsion Client Get the latest program from the server .
Four 、 Parent child class serialization
- Serialization , Save only the state of the object , Regardless of the object’s method ;
- The parent class implements Serializable, Subclasses automatically implement serialization , When serializing subclasses , The property value of the parent class will also be saved , So subclasses don’t need to show the implementation Serializable;
- The parent class does not implement Serializable, Subclass implementation Serializable, When serializing subclasses , The property value of the parent class Will not be saved , And the parent class must have no parameter construction ( Because there is no parent property value when deserializing , When instantiating an object, there are only subclass property values ).
Let’s not write practical examples here , If you are interested, you can verify it by yourself .
5、 … and 、 Custom Serialization
During serialization , The virtual machine tries to call the writeObject and readObject Method , User defined serialization and deserialization , If there is no such way , The default call is ObjectOutputStream Of defaultWriteObject Methods and ObjectInputStream Of defaultReadObject Method . User defined writeObject and readObject Method allows the user to control the serialization process , For example, the value of serialization can be changed dynamically during serialization .
Take a look at the following example :
public class Test implements Serializable {
private static final long serialVersionUID = 1L;
private String account = "beifengtz";
private String password = "123456";
public String getAccount() {
return account;
}
public String getPassword() {
return password;
}
private void readObject(ObjectInputStream in) {
try {
System.out.println("------ Start deserializing ------");
ObjectInputStream.GetField readField = in.readFields();
Object obj = readField.get("password", "");
System.out.println(" Password to decrypt :" + obj);
password = String.valueOf(Integer.parseInt((String) obj) / 1000);
System.out.println(" Decrypted password :" + password);
System.out.println("------ End of deserialization ------");
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
private void writeObject(ObjectOutputStream out) {
try {
System.out.println("------ Start serializing ------");
ObjectOutputStream.PutField putField = out.putFields();
String encrypt = String.valueOf(Integer.parseInt(password) * 1000);
putField.put("password", encrypt);
putField.put("account", account);
System.out.println(" Real password :" + password);
System.out.println(" Encrypted password :" + encrypt);
out.writeFields();
System.out.println("------ End of serialization -----");
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("serFile"));
out.writeObject(new Test());
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("serFile"));
Test test = (Test) in.readObject();
in.close();
System.out.println(" Password received after deserialization :" + test.getPassword());
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Look at the results
------ Start serializing ------
Real password :123456
Encrypted password :123456000
------ End of serialization -----
------ Start deserializing ------
Password to decrypt :123456000
Decrypted password :123456
------ End of deserialization ------
Password received after deserialization :123456
6、 … and 、 Storage of multi object serialization
about JDK Serialization of is not simply a binary text append store , But there are some optimizations . Its multi object serialization storage method is as follows :
- If objects stored multiple times are objects of different classes , The serialized binary content is appended directly to the text ;
- If the object stored multiple times is the same object of the same class , And its properties are exactly the same , After writing binary for the first time , The subsequent serialization only holds reference and control information , The rest of the same information is reused , It’s not a text addition ;
- If the object stored multiple times is the same object of the same class , However, the object contents are changed during multiple writes , The virtual machine knows that a same object has been written to the file according to the reference relationship , Save only the first written object , The object modification after the first serialization cannot be saved ;
- If the objects stored multiple times are different objects of the same class , Class information is also reused in serialization , Only the reference and control information of different properties of different objects are saved , Reuse the same properties .
Take a look at the following four different scenarios , Have you ever met ?
The following four scenarios are based on the following two classes for serialization testing :
Test1 class
public class Test1 implements Serializable {
private Integer value;
public Test1(Integer value) {
this.value = value;
}
@Override
public String toString() {
return "Test1{" +
"value=" + value +
'}';
}
}
Test2 class
public class Test2 implements Serializable {
private String content;
public Test2(String content) {
this.content = content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "Test2{" +
"content='" + content + '\'' +
'}';
}
}
6.1 Write the same object of the same class multiple times
Examples :
public static void main(String[] args) {
try {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("serFile"));
Test2 test = new Test2("1");
out.writeObject(test);
out.flush();
System.out.println(" Binary file length :" + new File("serFile").length());
out.writeObject(test);
out.flush();
out.close();
System.out.println(" Binary file length :" + new File("serFile").length());
} catch (IOException e) {
e.printStackTrace();
}
try {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("serFile"));
Test2 test_1 = (Test2) in.readObject();
Test2 test_2 = (Test2) in.readObject();
System.out.println(test_1);
System.out.println(test_2);
System.out.println(test_1 == test_2);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
Execution results :
Binary file length :75
Binary file length :80
Test2{content='1'}
Test2{content='1'}
true
6.2 Write the same object of the same class multiple times ( Modify the attributes one by one )
Examples :
public static void main(String[] args) {
try {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("serFile"));
Test2 test = new Test2("1");
out.writeObject(test);
out.flush();
System.out.println(" Binary file length :" + new File("serFile").length());
test.setContent("2"); // modify test Property content
out.writeObject(test);
out.flush();
out.close();
System.out.println(" Binary file length :" + new File("serFile").length());
} catch (IOException e) {
e.printStackTrace();
}
try {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("serFile"));
Test2 test_1 = (Test2) in.readObject();
Test2 test_2 = (Test2) in.readObject();
System.out.println(test_1);
System.out.println(test_2);
System.out.println(test_1 == test_2);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
Execution results :
Binary file length :75
Binary file length :80
Test2{content='1'}
Test2{content='1'}
true
6.3 Write different objects of the same class multiple times
Examples :
public static void main(String[] args) {
try {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("serFile"));
out.writeObject(new Test2("1"));
out.flush();
System.out.println(" Binary file length :" + new File("serFile").length());
out.writeObject(new Test2("2"));
out.flush();
out.close();
System.out.println(" Binary file length :" + new File("serFile").length());
} catch (IOException e) {
e.printStackTrace();
}
try {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("serFile"));
Test2 test_1 = (Test2) in.readObject();
Test2 test_2 = (Test2) in.readObject();
System.out.println(test_1);
System.out.println(test_2);
System.out.println(test_1 == test_2);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
Execution results :
Binary file length :75
Binary file length :85
Test2{content='1'}
Test2{content='2'}
false
6.4 Write different objects several times
Examples :
public static void main(String[] args) {
try {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("serFile"));
out.writeObject(new Test1(1));
out.flush();
System.out.println(" Binary file length :" + new File("serFile").length());
out.writeObject(new Test2("2"));
out.flush();
out.close();
System.out.println(" Binary file length :" + new File("serFile").length());
} catch (IOException e) {
e.printStackTrace();
}
try {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("serFile"));
Test1 test_1 = (Test1) in.readObject();
Test2 test_2 = (Test2) in.readObject();
System.out.println(test_1);
System.out.println(test_2);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
Execution results :
Binary file length :147
Binary file length :218
Test1{value=1}
Test2{content='2'}
Java Serialization knowledge summary
- Objects that need to be serialized must implement
Serializable
Interface , This is a declarative interface , There are no properties or methods , If the interface is not implemented, an error will be reported :NotSerializableException
- adopt ObjectOutputStream and ObjectInputStream Serializing and deserializing objects
- By transient The property value decorated by the keyword will not be saved in the serialization file , So the property value after deserialization is the default value of variable type . Here, for example. String Of gender Namely
null
- Serialization does not save static variables
- Whether the virtual machine allows deserialization , Not only depends on whether the class path and function code are consistent , A very important point is the serialization of two classes ID Is it consistent (private static final long serialVersionUID)
- For storage of multi object serialization , It’s not a simple binary addition , Virtual machine has some optimization to it , Reduce disk space usage or network transfer content size