Another difficult problem: Why do serialization and deserialization implement the Serializable interface

Another difficult problem: Why do serialization and deserialization implement the Serializable interface

table of Contents

  • Serialization and deserialization
  • When do you need to use serialization and deserialization?
  • Why do you need to implement the Serializable interface to implement serialization and deserialization?
  • Even if the Serializable interface is implemented, why should the value of the specified serialVersionUID be displayed?
  • Other features of Java serialization
  • Why won't the static attribute be serialized?

Recently, the company is doing service-oriented, and all the classes in the model package need to implement the Serializable interface, and at the same time, the value of the specified serialVersionUID must be displayed. Hearing this demand, several questions suddenly appeared in my mind, such as:

  • What are serialization and deserialization?
  • Why do you need to implement the Serializable interface to implement serialization and deserialization?
  • Even if the Serializable interface is implemented, why display the value of the specified serialVersionUID?
  • What value do I specify for serialVersionUID?

Let's answer these questions one by one.

Serialization and deserialization

  • Serialization: The process of converting an object into a sequence of bytes is called serialization of the object.
  • Deserialization: The process of restoring a byte sequence to an object is called object deserialization.

When do you need to use serialization and deserialization?

When we only run the Java instance in the local JVM, there is no need for serialization and deserialization at this time, but when we need to persist objects in memory to disk or database, when we need to communicate with the browser When interacting, when we need to implement RPC, serialization and deserialization are required at this time.

Do the first two scenarios that require serialization and deserialization make us have a big question? When we interact with the browser, and when we persist objects in memory to the database, it seems that all Did not go to serialization and deserialization, because we have not implemented the Serializable interface, but it has been running normally.

The following conclusions are given first:

As long as we persist or transmit the objects in memory, serialization and deserialization are required at this time.

reason:

Is the Serializable interface really not used when the server interacts with the browser? The JSON format actually converts an object into a string, so the data format when the server interacts with the browser is actually a string. Let's look at the source code of the String type:

public final class String     implements java.io.Serializable, Comparable<String>, CharSequence {     /\*\* The value is used  for  character storage./*/     private final char value\[\];     /\*\* Cache the hash code  for  the  string  \*/     private  int  hash;  //Default to 0     /\*\* use serialVersionUID from JDK  1.0 .2  for  interoperability/*/     private static final long serialVersionUID =  -6849794470754667710 L;     ...... } Copy code

The String type implements the Serializable interface and displays the value of the specified serialVersionUID.

Then let's look at the situation when the object is persisted to the database, the insert code in the Mybatis database mapping file:

<insert id= "insertUser"  parameterType= "org.tyshawn.bean.User" >     INSERT INTO t\_user(name, age) VALUES (#{name}, #{age}) </insert> Copy code

In fact, we are not persisting the entire object to the database, but persisting the properties of the object to the database, and these properties are the basic properties that implement the Serializable interface.

Why implement the Serializable interface?

After implementing the Serializable interface in Java, the JVM will help us achieve serialization and deserialization at the bottom level. If we do not implement the Serializable interface, then we can write a set of serialization and deserialization code by ourselves. As for how to write it, , Google you will know it in one click.

Why specify the value of serialVersionUID?

If the specified serialVersionUID is not displayed, the JVM will automatically generate a serialVersionUID according to the attribute during serialization, and then serialize it together with the attribute, and then perform persistence or network transmission.

During deserialization, JVM will automatically generate a new version of serialVersionUID according to the attributes, and then compare this new version of serialVersionUID with the old version of serialVersionUID generated during serialization. If they are the same, the deserialization is successful, otherwise an error will be reported.

If it shows that the serialVersionUID is specified, the JVM will still generate a serialVersionUID during serialization and deserialization, but the value is the value we display, so that the serialVersionUID of the new and old versions will be the same during deserialization.

In actual development, what problems will be caused if the specified serialVersionUID is not displayed? If our class is not modified after it is written, of course there will be no problem.

But this is impossible in actual development. Our class will continue to iterate. Once the class is modified, the old object deserialization will report an error. Therefore, in actual development, we will display the specified serialVersionUID, the value does not matter, as long as it does not change.

Write an example test:

(1) User class

Do not display the specified serialVersionUID.

public class User implements Serializable {     private String name;     private Integer age;     public String getName() {         return  name;     }     public void setName(String name) {         this.name = name;     }     public Integer getAge() {         return  age;     }     public void setAge(Integer age) {         this.age = age;     }     @Override     public String toString() {         return  "User{"  +                  "+ name +'\\'' +                 " , age = " + age +                 '}';     } } Copy code

(2) Test class

Serialize first, then deserialize.

public class SerializableTest {     private static void serialize(User user) throws Exception {         ObjectOutputStream oos =  new  ObjectOutputStream( new  FileOutputStream( new  File( "D:\\111.txt" )));         oos.writeObject(user);         oos. close ();     }     private static User deserialize() throws Exception{         ObjectInputStream ois =  new  ObjectInputStream( new  FileInputStream( new  File( "D:\\111.txt" )));          return  (User) ois.readObject();     }     public static void main(String\[\] args) throws Exception {         User user =  new  User();         user.setName( "tyshawn" );         user.setAge( 18 );         System.out. println ( "Result before serialization: "  + user);         serialize(user);         User dUser = deserialize();         System.out. println ( "Result after deserialization: " + dUser);     } } Copy code

(3) Results

Comment out the deserialization code first, execute the serialization code, and then add a property sex to the User class

public class User implements Serializable {     private String name;     private Integer age;     private String sex;     public String getName() {         return  name;     }     public void setName(String name) {         this.name = name;     }     public Integer getAge() {         return  age;     }     public void setAge(Integer age) {         this.age = age;     }     public String getSex() {         return  sex;     }     public void setSex(String sex) {         this.sex = sex;     }     @Override     public String toString() {         return  "User{"  +                  "+ name +'\\'' +                 " , age = " + age +                 " , sex = '" + sex + '/''  +                  '}' ;     } } Copy code

Then comment out the serialization code to execute the deserialization code, and the final result is as follows:

Result before serialization: User{name='tyshawn', age=18} Exception in thread "main" java.io.InvalidClassException: org.tyshawn.SerializeAndDeserialize.User; local class incompatible: stream classdesc serialVersionUID = 1035612825366363028, local class serialVersionUID = -1830850955895931978

The error result is that the serialVersionUID generated by serialization and deserialization are inconsistent.

Next, we display and specify a serialVersionUID based on the User class above

Final static serialVersionUID = Long Private  . 1 L; duplicated code

Perform the above steps again, and the test results are as follows:

Result before serialization: User{name='tyshawn', age=18} Result after deserialization: User{name='tyshawn', age=18, sex='null'}

After displaying the specified serialVersionUID, the problem of inconsistent serialVersionUID generated by serialization and deserialization is solved.

Other features of Java serialization

Let me talk about the conclusion first, the attributes modified by the transient keyword will not be serialized, and the static attributes will not be serialized.

Let's test this conclusion:

(1) User class

public class User implements Serializable {     private static final long serialVersionUID =  1 L;     private String name;     private Integer age;     private transient String sex;     private static String signature =  "The world in your eyes is what you look like" ;     public String getName() {         return  name;     }     public void setName(String name) {         this.name = name;     }     public Integer getAge() {         return  age;     }     public void setAge(Integer age) {         this.age = age;     }     public String getSex() {         return  sex;     }     public void setSex(String sex) {         this.sex = sex;     }     public static String getSignature() {         return  signature;     }     public static void setSignature(String signature) {         User.signature = signature;     }     @Override     public String toString() {         return  "User{"  +                  "+ name +'\\'' +                 " , age = " + age +                 " , sex= '" + sex +'/''  +                  ", signature='"  + signature +  '\\' '+                 ' } ';     } } Copy code

(2) Test class

public class SerializableTest {     private static void serialize(User user) throws Exception {         ObjectOutputStream oos =  new  ObjectOutputStream( new  FileOutputStream( new  File( "D:\\111.txt" )));         oos.writeObject(user);         oos. close ();     }     private static User deserialize() throws Exception{         ObjectInputStream ois =  new  ObjectInputStream( new  FileInputStream( new  File( "D:\\111.txt" )));          return  (User) ois.readObject();     }     public static void main(String\[\] args) throws Exception {         User user =  new  User();         user.setName( "tyshawn" );         user.setAge( 18 );         user.setSex( "man" );         System.out. println ( "Result before serialization: "  + user);         serialize(user);         User dUser = deserialize();         System.out. println ( "Result after deserialization: " + dUser);     } } Copy code

(3) Results

First comment out the deserialization code, execute the serialization code, then modify the User class signature = "Only you in my eyes", and then comment out the serialization code to execute the deserialization code, the final result is as follows:

The result before serialization: User(name='tyshawn', age=18, sex='man', signature='The world in your eyes is what you look like') The result after deserialization: User(name=' tyshawn', age=18, sex='null', signature='Only you in my eyes'}

Why won't the static attribute be serialized?

Because serialization is for the object, and the static attribute exists in preference to the object, and is loaded with the loading of the class, so it will not be serialized.

Seeing this conclusion, someone will ask, serialVersionUID is also modified by static, why serialVersionUID will be serialized? 

In fact, the serialVersionUID attribute is not serialized. JVM will automatically generate a serialVersionUID when serializing the object, and then assign the serialVersionUID attribute value that we display and specify to the automatically generated serialVersionUID.

Source: tyshawnlee.blog.csdn.net/article/details/100097019