java對(duì)象序列化與反序列化原理解析
這篇文章主要介紹了java對(duì)象序列化與反序列化原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
一、序列化和反序列化的概念
對(duì)象轉(zhuǎn)換為字節(jié)序列的過(guò)程稱為對(duì)象的序列化。把字節(jié)序列恢復(fù)為對(duì)象的過(guò)程稱為對(duì)象的反序列化。
二、序列化和反序列化的作用
對(duì)象的序列化主要有兩種用途:
- 把對(duì)象的字節(jié)序列永久地保存到硬盤上,通常存放在一個(gè)文件中。
- 在網(wǎng)絡(luò)上傳送對(duì)象的字節(jié)序列。網(wǎng)絡(luò)上傳輸?shù)亩际嵌M(jìn)制序列。
在很多應(yīng)用中,需要對(duì)某些對(duì)象進(jìn)行序列化,讓它們離開(kāi)內(nèi)存空間,存到物理硬盤,以便長(zhǎng)期保存。比如最常見(jiàn)的是Web服務(wù)器中的Session對(duì)象,當(dāng)有10萬(wàn)用戶并發(fā)訪問(wèn),就有可能出現(xiàn)10萬(wàn)個(gè)Session對(duì)象,內(nèi)存可能吃不消,于是Web容器就會(huì)把一些seesion先序列化到硬盤中,等要用了再把保存在硬盤中的對(duì)象還原到內(nèi)存中。
當(dāng)兩個(gè)進(jìn)程在進(jìn)行遠(yuǎn)程通信時(shí),彼此可以發(fā)送各種類型的數(shù)據(jù)。無(wú)論是何種類型的數(shù)據(jù),都會(huì)以二進(jìn)制序列的形式在網(wǎng)絡(luò)上傳送。
發(fā)送方需要把這個(gè)Java對(duì)象轉(zhuǎn)換為字節(jié)序列,才能在網(wǎng)絡(luò)上傳送;接收方則需要把字節(jié)序列再恢復(fù)為Java對(duì)象。
三、JDK類庫(kù)中的序列化API
java.io.ObjectOutputStream代表對(duì)象輸出流,它的writeObject(Object obj)方法可把指定的obj對(duì)象進(jìn)行序列化,把得到的字節(jié)序列寫(xiě)到一個(gè)目標(biāo)輸出流中。
java.io.ObjectInputStream代表對(duì)象輸入流,它的readObject()方法從一個(gè)源輸入流中讀取字節(jié)序列,再把它們反序列化為一個(gè)對(duì)象,并將其返回。
只有實(shí)現(xiàn)了Serializable和Externalizable接口的類的對(duì)象才能被序列化。Externalizable接口繼承自 Serializable接口,實(shí)現(xiàn)Externalizable接口的類完全由自身來(lái)控制序列化的行為,而僅實(shí)現(xiàn)Serializable接口的類可以 采用默認(rèn)的序列化方式 。
對(duì)象序列化包括如下步驟:
1) 創(chuàng)建一個(gè)對(duì)象輸出流,它可以包裝一個(gè)其他類型的目標(biāo)輸出流,如文件輸出流;
2) 通過(guò)對(duì)象輸出流的writeObject()方法寫(xiě)對(duì)象。
對(duì)象反序列化的步驟如下:
1) 創(chuàng)建一個(gè)對(duì)象輸入流,它可以包裝一個(gè)其他類型的源輸入流,如文件輸入流;
2) 通過(guò)對(duì)象輸入流的readObject()方法讀取對(duì)象。
四、serialVersionUID的作用
serialVersionUID: 字面意思上是序列化的版本號(hào),凡是實(shí)現(xiàn)Serializable接口的類都有一個(gè)表示序列化版本標(biāo)識(shí)符的靜態(tài)變量。實(shí)現(xiàn)Serializable接口的類如果類中沒(méi)有添加serialVersionUID,則會(huì)報(bào)一個(gè)警告。
serialVersionUID有兩種生成方式:
采用img這種方式生成的serialVersionUID是1L,例如:
1 private static final long serialVersionUID = 1L;
采用img這種方式生成的serialVersionUID是根據(jù)類名,接口名,方法和屬性等來(lái)生成的,例如:
1 private static final long serialVersionUID = 4603642343377807741L;
serialVersionUID 這個(gè)序列化版本號(hào)的作用就是當(dāng)有修改的時(shí)候,會(huì)兼容之前的版本內(nèi)容,因?yàn)樾薷那昂蟮膕erialVersionUID 是一樣的,如果修改前后的序列化版本號(hào)不同,則會(huì)反序列化失敗。也就是說(shuō)當(dāng)我們自己去指定了serialVersionUID,就可以保證在這么多類中,這個(gè)編號(hào)是唯一的。這樣我們就可以在序列化后,去修改之前的類,例如添加屬性字段,或者新增一個(gè)方法而不會(huì)影響到后期的還原,還原后的對(duì)象照樣可以使用,而且還多了方法或者屬性可以用。
五、serialVersionUID的取值
serialVersionUID的取值是Java運(yùn)行時(shí)環(huán)境根據(jù)類的內(nèi)部細(xì)節(jié)自動(dòng)生成的。如果對(duì)類的源代碼作了修改,再重新編譯,新生成的類文件的serialVersionUID的取值有可能也會(huì)發(fā)生變化。
類的serialVersionUID的默認(rèn)值完全依賴于Java編譯器的實(shí)現(xiàn),對(duì)于同一個(gè)類,用不同的Java編譯器編譯,有可能會(huì)導(dǎo)致不同的 serialVersionUID,也有可能相同。為了提高serialVersionUID的獨(dú)立性和確定性,強(qiáng)烈建議在一個(gè)可序列化類中顯示的定義serialVersionUID,為它賦予明確的值。
顯式地定義serialVersionUID有兩種用途:
在某些場(chǎng)合,希望類的不同版本對(duì)序列化兼容,因此需要確保類的不同版本具有相同的serialVersionUID;
在某些場(chǎng)合,不希望類的不同版本對(duì)序列化兼容,因此需要確保類的不同版本具有不同的serialVersionUID。
六、總結(jié)
序列化是將對(duì)象進(jìn)行序列化,目的是方便存儲(chǔ)和在網(wǎng)絡(luò)中進(jìn)行傳輸。
但是需要注意的是序列化保存的是對(duì)象的狀態(tài),靜態(tài)變量屬于類的狀態(tài),因此 序列化并不保存靜態(tài)變量。
如果不想某個(gè)變量被序列化,則可以在該變量前加上Transient 關(guān)鍵字。
Transient 關(guān)鍵字的作用是控制變量的序列化,在變量聲明前加上該關(guān)鍵字,可以阻止該變量被序列化到文件中,在被反序列化后,transient 變量的值被設(shè)為初始值,如 int 型的是 0,對(duì)象型的是 null。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
如何使用BeanUtils.copyProperties進(jìn)行對(duì)象之間的屬性賦值
這篇文章主要介紹了使用BeanUtils.copyProperties進(jìn)行對(duì)象之間的屬性賦值,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05idea復(fù)制module(項(xiàng)目)并在一個(gè)窗口展示的教程詳解
這篇文章主要介紹了idea復(fù)制module(項(xiàng)目)并在一個(gè)窗口展示的方法,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06SpringBoot詳細(xì)分析自動(dòng)裝配原理并實(shí)現(xiàn)starter
相對(duì)于傳統(tǒng)意義上的Spring項(xiàng)目,SpringBoot具有開(kāi)箱即用,簡(jiǎn)化配置,內(nèi)置Tomcat等等等等一系列的特點(diǎn)。在這些特點(diǎn)中,最重要的兩條就是約定優(yōu)于配置和自動(dòng)裝配2022-07-07詳解Spring連接數(shù)據(jù)庫(kù)的幾種常用的方式
本篇文章主要介紹了Spring連接數(shù)據(jù)庫(kù)的幾種常用的方式,具有一定的參考價(jià)值,有需要的可以了解一下。2016-12-12java將String字符串轉(zhuǎn)換為L(zhǎng)ist<Long>類型實(shí)例方法
在本篇文章里小編給大家整理的是關(guān)于java將String字符串轉(zhuǎn)換為L(zhǎng)ist<Long>類型實(shí)例方法,需要的朋友們可以參考下。2020-03-03Java concurrency集合之CopyOnWriteArraySet_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
CopyOnWriteArraySet基于CopyOnWriteArrayList實(shí)現(xiàn),其唯一的不同是在add時(shí)調(diào)用的是CopyOnWriteArrayList的addIfAbsent(若沒(méi)有則增加)方法2017-06-06java實(shí)現(xiàn)簡(jiǎn)單猜數(shù)字
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單猜數(shù)字,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05