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

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