java中對(duì)象的序列化與反序列化深入講解
引言:
序列化就是一種用來(lái)處理對(duì)象流的機(jī)制,所謂對(duì)象流也就是將對(duì)象的內(nèi)容進(jìn)行流化??梢詫?duì)流化后的對(duì)象進(jìn)行讀寫操作,也可將流化后的對(duì)象傳輸于網(wǎng)絡(luò)之間。序列化是為了解決在對(duì)對(duì)象流進(jìn)行讀寫操作時(shí)所引發(fā)的問(wèn)題。
- 把對(duì)象轉(zhuǎn)換為字節(jié)序列的過(guò)程稱為對(duì)象的序列化。
- 把字節(jié)序列恢復(fù)為對(duì)象的過(guò)程稱為對(duì)象的反序列化。
在很多應(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ì)象。
序列化是將對(duì)象的狀態(tài)信息轉(zhuǎn)換為可以存儲(chǔ)或傳輸?shù)男问降倪^(guò)程,在序列化期間,對(duì)象將其帶你過(guò)去的狀態(tài)寫入到臨時(shí)或持儲(chǔ)存區(qū),反序列化就是重新創(chuàng)建對(duì)象的過(guò)程,此對(duì)象來(lái)自于臨時(shí)或持久儲(chǔ)存區(qū)。
序列化的作用:
就好比如存儲(chǔ)數(shù)據(jù)到數(shù)據(jù)庫(kù),將一些數(shù)據(jù)持久化到數(shù)據(jù)庫(kù)中,而有時(shí)候需要將對(duì)象持久化,雖然說(shuō)將對(duì)象狀態(tài)持久化的方式有很多,但是java給我們提供了一種很便捷的方式,那就是序列化,序列化可以實(shí)現(xiàn)對(duì)象到文件之間的直接轉(zhuǎn)換,實(shí)現(xiàn)細(xì)節(jié)對(duì)我們隱藏。
具體的三種用途:
- 將對(duì)象的狀態(tài)信息持久化保存到硬盤上
- 將對(duì)象信息在網(wǎng)絡(luò)上傳輸
- 深度克?。ň褪切蛄谢笤俜葱蛄谢?br />
方式一:實(shí)現(xiàn)Serializable接口,通過(guò)序列化流
實(shí)現(xiàn)Serializable接口,通過(guò)ObjectOutputStream和ObjectInputStream將對(duì)象序列化和反序列化。
import java.io.*;
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
// User user = new User("gol",22);
// ByteArrayOutputStream bo = new ByteArrayOutputStream();
// ObjectOutputStream oo = new ObjectOutputStream(bo);
// oo.writeObject(user);//序列化.user寫入字節(jié)數(shù)組流中
// ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
// ObjectInputStream oi = new ObjectInputStream(bi);
// User userSer = (User) oi.readObject();//反序列化
// System.out.println(userSer);
User user = new User("gol",22);
FileOutputStream fos = new FileOutputStream("a.txt");
ObjectOutputStream oo = new ObjectOutputStream(fos);
oo.writeObject(user);//序列化.user寫入文件中
FileInputStream fis = new FileInputStream("a.txt");
ObjectInputStream oi = new ObjectInputStream(fis);
User userSer = (User) oi.readObject();//反序列化
System.out.println(userSer);
oi.close();
fis.close();
oo.close();
fos.close();
}
}
方式二:實(shí)現(xiàn)Externalizable接口,重寫writeExternal和readExternal方法
Externalizable接口繼承了Serializable接口,替我們封裝了兩個(gè)方法,一個(gè)用于序列化,一個(gè)用于反序列化。這種方式是將屬性序列化,注意這種方式transient修飾詞將失去作用,也就是說(shuō)被transient修飾的屬性,只要你在writeExternal方法中序列化了該屬性,照樣也會(huì)得到序列化。
import java.io.*;
public class User implements Externalizable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(this.name);//將屬性分別序列化
out.writeObject(this.age);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.name=(String)in.readObject();//反序列化屬性
this.age=(int)in.readObject();
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileOutputStream fos = new FileOutputStream("a.txt");
ObjectOutputStream oo = new ObjectOutputStream(fos);
FileInputStream fis = new FileInputStream("a.txt");
ObjectInputStream oi = new ObjectInputStream(fis);
User user = new User("gol",19);
user.writeExternal(oo);//序列化
User userEnr = new User();
userEnr.readExternal(oi);//反序列化
System.out.println(userEnr);
oi.close();
fis.close();
oo.close();
fos.close();
}
}
總結(jié):
注意以下三點(diǎn):
- Serializable接口是標(biāo)記接口,是個(gè)空接口,用于標(biāo)識(shí)該類可以被序列化。
- transient是屬性修飾符,被其修飾的屬性將不會(huì)被序列化,但是使用方式二的話,明確寫明該屬性序列化同樣可以得到序列化。
- serialVersionUID屬性是類的序列化標(biāo)識(shí)ID,若序列化的對(duì)象和反序列化的對(duì)象其serialVersionUID屬性不一樣則會(huì)報(bào)錯(cuò)。
好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- java對(duì)象序列化與反序列化原理解析
- 實(shí)例分析java對(duì)象的序列化和反序列化
- Java對(duì)象的XML序列化與反序列化實(shí)例解析
- Java將對(duì)象寫入文件讀出_序列化與反序列化的實(shí)例
- Java對(duì)象的序列化與反序列化詳解
- Java IO流對(duì)象的序列化和反序列化實(shí)例詳解
- 詳解Java 對(duì)象序列化和反序列化
- java對(duì)象的序列化和反序列化
- java 對(duì)象的序列化和反序列化詳細(xì)介紹
- GSON實(shí)現(xiàn)Java對(duì)象的JSON序列化與反序列化的實(shí)例教程
- 詳解Java中對(duì)象序列化與反序列化
- Java中對(duì)象序列化與反序列化詳解
- java對(duì)象序列化與反序列化的默認(rèn)格式和json格式使用示例
- 深入理解Java對(duì)象的序列化與反序列化的應(yīng)用
- 深入理解Java序列化與反序列化
相關(guān)文章
深入了解SpringBoot中的統(tǒng)一返回和統(tǒng)一異常處理
這篇文章主要為大家詳細(xì)介紹了SpringBoot項(xiàng)目中常用的統(tǒng)一返回結(jié)果和統(tǒng)一異常處理,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2024-01-01
帶有@Transactional和@Async的循環(huán)依賴問(wèn)題的解決
這篇文章主要介紹了帶有@Transactional和@Async的循環(huán)依賴問(wèn)題的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
SpringBoot項(xiàng)目yml配置文件不自動(dòng)提示解決方案
這篇文章主要介紹了SpringBoot項(xiàng)目配置文件.yaml/.yml文件編寫時(shí)沒(méi)有自動(dòng)提示的解決方案,文章通過(guò)圖文結(jié)合的方式給大家講解的非常詳細(xì),需要的朋友可以參考下2024-06-06
java中常見(jiàn)XML解析器的使用詳解(JAXP,DOM4J,Jsoup,JsoupXPath)
為了處理和操作XML數(shù)據(jù),我們需要使用XML解析器,本文將介紹幾種常用的XML解析器,包括JAXP、DOM4J、Jsoup和JsoupXPath,需要的小伙伴可以參考一下2023-11-11
Maven入門之使用Nexus搭建Maven私服及上傳下載jar包
這篇文章主要介紹了Maven入門之使用Nexus搭建Maven私服及上傳下載jar包,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12
java開(kāi)發(fā)中使用IDEA活動(dòng)模板快速增加注釋的方法
這篇文章主要介紹了java開(kāi)發(fā)中使用IDEA活動(dòng)模板快速增加注釋,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12

