java序列化、反序列化、serialVersionUID

一、Serialization、Deserialization

Serialization is a mechanism of converting the state of an object into a byte stream.
Deserialization is the reverse process where the byte stream is used to recreate the actual Java object in memory. This mechanism is used to persist the object.
在这里插入图片描述
序列化的是成员变量的值,除了Transient、static variables.Default values(reference is null;primitive type is default value) for that datatype will be set during deserialization.

Transient : If any variable is defined by using keyword “transient”, then object will not serialize that variable. During deserialization default value of that datatype will be set.
Static : as static variables are class level variables, so it is not serialzed as the object state.

二、why Serialize

  • store/persist data/state of an object:在JVM级别,对象是在堆中创建的;在计算机结构中,它是在内存中创建的,在程序运行完,对象消失。序列化可以长久的保存此对象的数据。
  • Transmit data/state of an object:使得这个对象可以在不同location使用。比如transmit over network then reconstruct it in a different place.
  • Clone an object without overring clone.

从存储设备讲:
If you have a data structure that you need to store on disk or transfer across a network, serialization is a good solution. The disk or network know how to store or transfer data, but they don’t understand the way a particular language stores data. Serialization provides a standard process for a language or programming environment to translate its data structures into a standard format. If multiple languages agree on the format, serialization can even provide a way for otherwise incompatible systems to exchange data.

三、how Serialize

Interface Serializable
Serializable is a marker interface (has no data member and method). It is used to “mark” Java classes so that the objects of these classes may get a certain capability. The Cloneable and Remote are also marker interfaces.
Serializable接口是marker interface(没有数据成员和方法)。其他marker interface比如Cloneable、Remote

The String class and all the wrapper classes implement the java.io.Serializable interface by default.
String 或原始类型的包装类均实现了Serializable接口。

wrapper classes is a class whose object wraps or contains a primitive data types.

序列化必须满足这两条:
①It must be implemented by the class whose object you want to persist.
②Associated objects must be implementing Serializable interface.
(若不实现Serializable接口,在编译时不会报错,但运行会报错)

class A implements Serializable{

// B also implements Serializable
// interface.
B ob=new B();  
}

serialize Object → File :create an ObjectOutputStream with a FileOutputStream.
OutputStream os=new FileOutputStream("a.txt");
serialize Object → sequences of bytes →File

**deserialize File→ Object ** :create an ObjectInputStream with a FileInputStream.
InputStream os=new FileInputStream("a.txt");
File → sequences of bytes →serialize Object
Constructor of object is never called when an object is deserialized.

也可以用Serializable子接口Externalizable

四、serialVersionUID

private static final long serialVersionUID = 4L;

During serialization, java runtime associates a version number with each serializable class. This number called serialVersionUID, which is used during deserialization to verify that the sender ( the person who serializes) and receiver ( the person who deserializes) of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender’s class, then deserialization will result in an InvalidClassException.must be static, final, and of type long.
serialVersionUID 表示可序列化类的版本,在反序列化对象时,用来确认序列化与反序列化该对象所使用的类的版本是否兼容。如果类的版本不一致,那么反序列化将不能正常进行,抛出InvalidClassException。修饰符固定了static final long,也建议private,这样子类不能使用它。

The default serialVersionUID computation is highly sensitive to class details and may vary from different JVM implementation.
因为Serializable没有方法或成员,若不写serialVersionUID,它会在运行期间,生成。生成的序列化依据class name, implemented interfaces, and all public and protected members.若其中一个更改,则序列化会改变。最好还是明确定义,因为不同的编译器可能产生不同的类信息,从而产生InvalidClassException。

为了保证一致的serialVersionUID,即使在不同的编译器之间,则需要明确的写serialVersionUID 的值。

若对serialVersionUID进行修改,则反序列化之前版本的,会失败。因为序列号不一致。

实例:https://dzone.com/articles/what-is-serialversionuid

五、继承关系中序列化表现

If parent class implements interface serializable then all the child classes state will be serialized with Parent class object.(序列化子类时会保存父类的变量值)
If child class implements interface serializable and parent not,then program will run but only child will be serialized but parent class will not .(序列化子类时父类的变量值不会保存)

参考:
https://howtodoinjava.com/java/serialization/serialversionuid/
https://dzone.com/articles/what-is-serialversionuid
https://www.geeksforgeeks.org/serialization-in-java/
https://www.youtube.com/watch?v=6MisF1sxBTo

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章