---
# System prepended metadata

title: Serialization
tags: [Java]

---

# Serialization
###### tags: `Java`
### Introduce

意義：將一個物件表示為位元組序列
必要條件：實作java.io.Serializable介面

1. 實例變數若是參考型態且沒有被transient修飾，則也必須實作java.io.Serializable介面，否則序列化會Error
2.  在同一次序列化過程中同一個Object序列化多次，只有第一次會成功
	 JVM序列化演算法 :
			 1. 序列化後所有物件都會有一個編碼
			 2. 如果再次使用到序列化過的物件則只會輸出編碼
	因此會造成序列化後修改資料，再序列化時不會更新後面修改的內容
	ps:經測試同一次的定義為同一個ObjectOutputStream實體
3. 可透過修飾字**transient** 來決定不需要序列化的屬性
4. 自定義序列化
5. 類別變數不會被序列化
6. 反序列化必須有原始的class檔案
7. serialVersionUID用來判斷class檔案是否相同，如果不同會拋錯
版本號可自己指定，或者由JVM計算後指定，不同版本的JVM即使是相同的class也可能產生不同的UID。是否需要修改這個UID則可判斷實例變數是否有調整為依據，如果是修改方法、類別變數、transient變數則不需要調整

自定義序列化-透過override下列方法

	    private void writeObject(java.io.ObjectOutputStream out) throws IOException；  
		private void readObject(java.io.ObjectIutputStream in) throws IOException,ClassNotFoundException;  
		private void readObjectNoData() throws ObjectStreamException;

其他自定義序列化方法
	
		ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException; 
在序列化過程中較writeObject優先調用，並依照自定義方法**替換**掉原先要被序列化的物件

		ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;	 
在反序列化過程較readObject優先調用，並依照自定義方法**替換**掉反序列化的物件 ( 實現單例模式方法一)



**Externalizable**
與Serializable不同之處為實作之後，必須實作

		public void writeExternal(ObjectOutput out) throws IOException
		public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
  
即使有定義writeObject、readObject，在寫出、讀入時仍優先使用writeExternal、readExternal




[https://juejin.im/post/5ce3cdc8e51d45777b1a3cdf](https://juejin.im/post/5ce3cdc8e51d45777b1a3cdf)[https://www.jianshu.com/p/d757e6da01d4](https://www.jianshu.com/p/d757e6da01d4)
[https://www.cnblogs.com/binarylei/p/10987933.html](https://www.cnblogs.com/binarylei/p/10987933.html)
[https://www.jianshu.com/p/3e3d86716f76](https://www.jianshu.com/p/3e3d86716f76)