First look and then like, give yourself a little time to think, after thinking, please directly wechat search “Java learning way”, follow him. If you have suggestions for this article, please contact me on wechat: StudyJava

We all know that we implement the Serializeable interface when we create an object, but why? When do you do that? Is there anything weird about doing this? Miao almost confused herself with a third company…


Now let’s have a brief understanding of this knowledge point with Amiao…

sequence

Serialization is defined as encoding an object into a byte stream (I/O); The opposite operation is called deserialization.

The purpose of serialization is to facilitate data transfer and storage to disk (write a Java object to disk or transfer to another computer on the network, then we need to convert the object to byte stream for network transfer. For this general operation, serialization emerged to unify these formats.

Serialization is simply a mechanism for processing streams of objects. After converting an object into a sequence of bytes, it can be saved on disk or transmitted over the network for later restoration to the original object. Serialization allows objects to exist independently of program execution.

Usage scenarios: All objects that can be transferred over the network must be serializable, such as RMI (Remote Method Invoke). The parameters passed in or objects returned are serializable, otherwise an error will occur; All Java objects that need to be saved to disk must be serializable. For example, when Redis stores an object as a string, if the object is serialized, it simply stores the object directly (Java automatically converts the object into a serialized byte stream). Otherwise, you need to convert the object into A JSON string for storage, but JSON strings are more memory efficient.

It is generally recommended that every JavaBean class created by a program implement the Serializeable interface. But implementing the Serializeable interface also requires care. As mentioned in Article 74 of Effective Java:


How to serialize

In Java, a class can be serialized as long as it implements the Java.io.Serializable interface (enumerated classes can also be serialized).

Enum implements the Serializable interface, so objects of enumerated types can be serialized by default.

// DeletedEnum class, which represents the exit flag@Getter
@AllArgsConstructor
public enum DeletedEnum {
 NO_DELETED(0,"Not deleted"),
 DELETED(1,"Deleted");   public final Integer status;  public final String name; } Copy the code

The following is the java.lang.enum class:


A normal class can implement serialization by implementing the Serializable interface:

@Data
public class User implements Serializable {
// Serialize the version number    private static final long serialVersionUID = 1111013L;

 transient private String name;  private int age;   public static void main(String[] args) {  User user = new User();  user.setAge(12);  user.setName(Little Luffy);  System.out.println(user);  } } Copy the code

The following output is displayed:

User(name= luffy, age=12)Copy the code

Why can a class that implements the Serializable interface be serialized?

This is because it uses ObjectOutputStream to persist objects to a file, using the writeObject method, which in turn calls the following methods:

/ * *     * Underlying writeObject/writeUnshared implementation.
* /    private void writeObject0(Object obj, boolean unshared) throws IOException {
... // remaining cases  if (obj instanceof String) {  writeString((String) obj, unshared);  } else if (cl.isArray()) {  writeArray(obj, desc, unshared);  } else if (obj instanceof Enum) { writeEnum((Enum<? >) obj, desc, unshared); } else if (obj instanceof Serializable) {  writeOrdinaryObject(obj, desc, unshared);  } else {  if (extendedDebugInfo) {  throw new NotSerializableException(  cl.getName() + "\n" + debugInfoStack.toString());  } else {  throw new NotSerializableException(cl.getName());  }  } ... } Copy the code

As you can see from the above code, if the object being written is of type String, or array, or Enum, or Serializable, then the object can be serialized, otherwise NotSerializableException is thrown.

That is, String objects, enumerated objects, and array objects can be serialized by default, and the default serialization version number is generated.

The Externalizable interface and the transient keyword can be serialized using the Externalizable interface. Serializable interface can be serialized using the Externalizable interface and the transient keyword.


How do I automatically generate serialized version numbers

idea IDE

Install the serialVersionUID plug-in.


eclipse

Generally speaking, there are two types of generation:

  • One is the default 1L, for example:private static final long serialVersionUID = 1L;
  • One is to generate a 64-bit hash field based on the class name, interface name, member methods, attributes, and so on. After serialization, a yellow wavy underline appears on the class name. Select the first item and add the generated serial version identifier to automatically generate one.

The use of serialized version numbers

The explanation in the java.io.Serializable documentation goes like this:


The general meaning is as follows:

Deserialization must have a class file, but as the project is upgraded, the class file is also upgraded. How can serialization ensure compatibility before and after upgrade?

The serialization runtime is associated with each serializable class with a version number, called the serialVersionUID, which is used during deserialization to verify that the sender and receiver of the serialized object have loaded the serializable compatible classes for that object. Deserialization results in an InvalidClassException if the receiver has loaded a class for the object with a different serialVersionUID than the corresponding sender class. Serializable classes can explicitly declare their own serialVersionUID by declaring a field named serialVersionUID, which must be static, final, and of type long:

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
Copy the code

As long as the version number is the same, the object can be deserialized correctly even if the serialization property is changed.

@Data
public class User implements Serializable {
// Serialize the version number    private static final long serialVersionUID = 1111013L;
    private String name;
 private int age; } Copy the code

If the version number of the class used for deserialization is not the same as that used for deserialization, deserialization will report an InvalidClassException.


If a serializable class does not explicitly declare a serialVersionUID, the serializable runtime computes the default serialVersionUID value for the class based on aspects of the class, as described in the Java (TM) object serialization specification. However, it is strongly recommended that all serializable classes explicitly declare the serialVersionUID value, as the default serialVersionUID calculation is highly sensitive to class details, which may vary depending on the compiler’s implementation, This can result in unexpected InvalidClassExceptions during deserialization.

Also, default values are not conducive to migration between JVMS. The class file may not have changed, but different JVMS may evaluate the rules differently, which also makes deserialization impossible.

Therefore, to ensure that the serialVersionUID value is consistent across Java compiler implementations, serializable classes must declare an explicit serialVersionUID value. It is strongly recommended that explicit serialVersionUID declarations use the private modifier where possible, because such declarations only apply to immediately declared class serialVersionUID fields that do not work as inherited members.

Finally, when an object is serialized using the default mechanism, not only the current object is serialized, but other objects referenced by that object are also serialized, and so on. Therefore, if an object contains member variables that are container-like objects, and the elements that these containers contain are container-like objects, the serialization process can be complicated and expensive.

reference

  • https://www.cnblogs.com/kubixuesheng/p/10350523.html
  • https://stackoverflow.com/questions/285793/what-is-a-serialversionuid-and-why-should-i-use-it
  • https://juejin.cn/post/6844903848167866375
  • Effective Java, Chinese edition 2

I am Amiao, and your [Sanlian] is the biggest motivation for amiao’s creation. If there are any mistakes or suggestions in this blog, please leave a comment!

The article is constantly updated, you can search “The way of Java learning” on wechat to read it in the first time, reply [666] I prepared the necessary e-book programmer + more than hd teaching videos, as well as surprise interview questions, welcome to pick up.