1. 程式人生 > >對java序列化和反序列化的理解和測試

對java序列化和反序列化的理解和測試

首先需要說明的是,目前的傳輸和儲存多以json為主,連xml應用看上去都不那麼廣泛了。

於是,我們需要對自己寫的類進行序列化的操作機會變少了。

但,若我們對序列化有了瞭解,總是對於理解一些問題有幫助的。(其中序列化三個字可以換成任何技術)

今天要說的就是下面這個東西

static final long serialVersionUID = -3387516993124229948L;

序列化的概念

序列化:把物件轉化為位元組序列的過程。

反過來說就是反序列化。

序列化的應用

1、儲存物件,可以是永久的儲存在硬碟的一個檔案上,也可以是儲存在redis支援序列化儲存的容器中。 2、網路上遠端傳輸物件。 提到serialVersionUID,可能有些人很久自己寫過了。其實你還是經常用的。
即使你用json進行序列化遠端傳輸,依舊要用到serialVersionUID。
即使是String也是一樣。

下面用程式碼說明一下序列化的過程

不用太多語言描述,語言描述反而看不懂,我自己是這麼認為。
上程式碼,不喜歡看程式碼的,請看註釋。
序列化和反序列化的測試類
package test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SVTest {
	public static void main(String[] args) throws Exception {
		// 序列化User物件
		SerializeUser();
		// 反序列User物件
		User user = DeserializeUser();
		System.out.println(user);
	}

	/**
	 * 序列化User物件
	 */
	private static void SerializeUser() throws FileNotFoundException,
			IOException {
		// 建立一個小明
		User user = new User(1,"小明");
		// ObjectOutputStream 物件輸出流
		ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(
				new File("D:/User.txt")));
		// 序列化輸出User物件
		oo.writeObject(user);
		System.out.println("序列化成功!");
		oo.close();
	}

	/**
	 * 反序列User物件
	 */
	private static User DeserializeUser() throws Exception, IOException {
		// ObjectInputStream 物件讀取流
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
				new File("D:/User.txt")));
		// 反序列化User物件
		User user = (User) ois.readObject();
		System.out.println("反序列化成功!");
		ois.close();
		return user;
	}
}


被序列化的User類
package test;

public class User {
	
	// ID
	private int id;
	// 姓名
	private String name;
	
	User(int id, String name) {
		this.id = id;
		this.name = name;
	}

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

執行main方法,控制檯報錯
這個錯誤,不做多解釋了,英文很好理解。 原因大家也都很清楚,User類沒有實現序列化介面。 接下來為User類新增序列化介面的實現
package test;

import java.io.Serializable;

public class User implements Serializable {
	
	// ID
	private int id;
	// 姓名
	private String name;
	
	User(int id, String name) {
		this.id = id;
		this.name = name;
	}

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

發現有警告
先忽略執行一遍看看結果。
成功了,趕緊慶祝一下。


為什麼有警告?說一說serialVersionUID

警告在提示,沒有serialVersionUID 自動生成:如果沒有會根據類名、屬性、方法等自動生成一個serialVersionUID,所以才是警告而非錯誤。 輔助新增:有兩種方式
第一種方式生成的是1L
private static final long serialVersionUID = 1L;

第二種是根據類名、屬性、方法等生成的
private static final long serialVersionUID = -6367006705587584157L;

自動生成和輔助新增的生成方式是一樣一樣的?
是的,一樣,或者不同的生成方式原理也相同。 沒有也行,有也行,那為啥還會有警告呢,乾脆不寫算了? 不對,因為輔助新增的動作並不是每次都做,也就是第一次輔助添加了,以後基本不會變了,即使本類有所改變。 而自動生成,則每次都會改變。 每次都改變又會如何呢? 還是用程式碼說明,程式碼對於程式設計師來說是最通俗易懂的。 將我們新增的serialVersionUID刪除,看看會出現什麼結果。 先執行一遍main方法,生成一個User.txt。 成功了!並沒有什麼影響啊。 繼續 為User類性增加一個屬性:年齡
package test;

import java.io.Serializable;

public class User implements Serializable {
	
	// ID
	private int id;
	// 姓名
	private String name;
	// 新增加的年齡屬性
	private String age;
	
	User(int id, String name) {
		this.id = id;
		this.name = name;
	}

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

此時,註釋掉main方法中的序列化方法,只執行反序列化方法。會如何呢? 報錯了,拒絕載入。 Exception in thread "main" java.io.InvalidClassException: test.User; 
local class incompatible: 
stream classdesc serialVersionUID = -6367006705587584157,
local class serialVersionUID = 5139856059457605582
原因就是兩次生成的serialVersionUID 不同。 結論: 環境的變化會導致生成serialVersionUID的變化,例如不同的編譯器生成的serialVersionUID有可能不同 被序列化類本身的變化,會導致serialVersionUID發生變化 這可能不是我們想看到的。 serialVersionUID應該是唯一的,確定的,獨立的。
應該顯示的定義serialVersionUID,並賦予明確的、唯一確定的值。 作用: 在某些場合,希望類的不同版本對序列化相容,因此需要確保類的不同版本具有相同的serialVersionUID。
在某些場合,不希望類的不同版本對序列化相容,因此需要確保類的不同版本具有不同的serialVersionUID。

相關推薦

java象的序列序列

底層 修飾 我們 puts nbsp tostring read one asics 一,對象的序列化,反序列化1.對象的序列化,就是將Object轉換成byte序列,反之叫對象的反序列化2.做序列化需要有流類,序列化流(ObjectOutputStream),是(字節的)

記一次使用JacksonJava物件序列序列的踩坑經歷

背景大概是這樣,專案中的兩個服務A和B依賴了同一個common包的Java類,A對該類json序列化,而B對其反序列化。在一次common包升級過程中,這個Java類中增加了一個屬性,由於B其實用不到這個屬性,就只把A給升級打包了,這就導致B在反序列化時出現了一個異常:com.fasterxml.j

Java物件的序列序列

                Java提供了將物件以位元組的形式寫入到磁碟中,在需要的時候在從磁碟中恢復的功能,在網路傳輸中非常

java序列序列理解測試

首先需要說明的是,目前的傳輸和儲存多以json為主,連xml應用看上去都不那麼廣泛了。 於是,我們需要對自己寫的類進行序列化的操作機會變少了。 但,若我們對序列化有了瞭解,總是對於理解一些問題有幫助的。(其中序列化三個字可以換成任何技術) 今天要說的就是下面這個東西 s

Java核心類庫-IO-象流(實現序列序列

.get throws 反序 code row cts new java cep 使用對象流來完成序列化和反序列化操作:   ObjectOutputStream:通過writeObject()方法做序列化操作的   ObjectInputStream:通過readObje

java中什麽是序列序列

zab question .com 程序 還原 破壞 ans 但我 實現 序列化:能夠把一個對象用二進制的表示出來。 類似我第一個字節表示什麽屬性名詞,第二個字節表示什麽屬性值,第幾個字段表示有幾個屬性等。 而且這個二進制可以寫到硬

json象的序列序列

name .cn .net序列化 object cnblogs json log con com //Json.NET序列化 string jsonData = JsonConvert.SerializeObject(對象model);

python基礎之繼承組合應用、序列序列,選課系統綜合示例

sel 初始 否則 通用 __init__ period 類型 反序列化 信息 繼承+組合應用示例 1 class Date: #定義時間類,包含姓名、年、月、日,用於返回生日 2 def __init__(self,name,year,mon,day):

序列序列的基本操作

bsp 序列 log png .cn ima images mage alt 對象序列化和反序列化的基本操作

java中的序列序列學習筆記

文件 track 反序列化 out val nts 鼠標 main version 須要序列化的Person類: package cn.itcast_07; import java.io.Serializable; /* * NotSerializableE

Java象寫入文件讀出——序列序列

ansi print 成員 trace 對象的引用 ack lose 靜態 spa Java類中對象的序列化工作是通過ObjectOutputStream和ObjectInputStream來完成的。 寫入: 1 File aFile=new File(

01. Java象的序列序列簡介

語音 log -c object height 通訊 圖片 二進制 進程    Java對象的序列化與反序列化 ; 給大家講解一下什麽是序列化 & 反序列化      當兩個進程進行遠程通訊的時候,彼此相互可以發送各種類型的數據,如文本,圖片,語音和視頻等無論是任何

Serializable 指示一個類可以序列;ICloneable支持克隆,即用與現有實例相同的值創建類的新實例(接口);ISerializable允許象控制其自己的序列序列過程(接口)

att 文本 所有 可能 成員 強制 void inter 適用於 Serializable : 序列化是指將對象實例的狀態存儲到存儲媒體的過程。在此過程中,先將對象的公共字段和私有字段以及類的名稱(包括類所在的程序集)轉換為字節流,然後再把字節流寫入數據流。在隨後對對象進

Java基礎-IO流象之序列序列

span 作者 創作 style -s 反序列化 ont 對象 io流                 Java基礎-IO流對象之序列化與反序列化                                     作者:尹正傑 版權聲明:原創作品,謝絕轉載!否則將追究

java基礎序--列序列

color tran public png gin jdk style 硬盤 brush 一、什麽是序列化和反序列化:   序列化:是指把java堆內存中的對象轉換成字節(二進制流)的過程。也就是通過某種方式將java對象存儲在磁盤內存中,這個過程稱為序列化   反序列化:

2018-07-25期 Java序列序列編程小案例

測試 product set pri get sof serial span not package cn.sjq.Serializable.java;import java.io.FileInputStream;import java.io.FileOutputStrea

Java 之 Serializable 序列序列的概念,作用的通俗易懂的解釋

計算 transient 全部 序列化對象 語義 meta person int 較高的 遇到這個 Java Serializable 序列化這個接口,我們可能會有如下的問題a,什麽叫序列化和反序列化b,作用。為啥要實現這個 Serializable 接口,也就是為啥要序列

Java-裝飾流-物件流 - 序列序列

ObjectInputStream(反序列化) & ObjectOutputStream(序列化) 1.先寫出後讀取 2.讀取的順序必須保持一致 3.不是所有的物件都能序列化,要加上serializable接口才行 當不想對物件中的某個屬性序列化時,在屬性中新增transie

java序列序列物件

import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; impo

Java 之 Serializable 序列序列的概念 通俗易懂!!!

轉自: https://blog.csdn.net/qq_27093465/article/details/78544505 遇到這個 Java Serializable 序列化這個介面,我們可能會有如下的問題a,什麼叫序列化和反序列化 b,作用。為啥要實現這個 Serializable