一文帶你解讀Java序列化和反序列化機(jī)制
Java 提供了一種對象序列化的機(jī)制,該機(jī)制中,一個(gè)對象可以被表示為一個(gè)字節(jié)序列,該字節(jié)序列包括該對象的數(shù)據(jù)、有關(guān)對象的類型的信息和存儲(chǔ)在對象中數(shù)據(jù)的類型。
將序列化對象寫入文件之后,可以從文件中讀取出來,并且對它進(jìn)行反序列化,也就是說,對象的類型信息、對象的數(shù)據(jù),還有對象中的數(shù)據(jù)類型可以用來在內(nèi)存中新建對象。
整個(gè)過程都是 Java 虛擬機(jī)(JVM)獨(dú)立的,也就是說,在一個(gè)平臺(tái)上序列化的對象可以在另一個(gè)完全不同的平臺(tái)上反序列化該對象。
類 ObjectInputStream 和 ObjectOutputStream 是高層次的數(shù)據(jù)流,它們包含反序列化和序列化對象的方法。
簡單來說:
- 序列化: 將數(shù)據(jù)結(jié)構(gòu)或?qū)ο筠D(zhuǎn)換成二進(jìn)制字節(jié)流的過程
- 反序列化:將在序列化過程中所生成的二進(jìn)制字節(jié)流轉(zhuǎn)換成數(shù)據(jù)結(jié)構(gòu)或者對象的過程
下面是序列化和反序列化常見應(yīng)用場景:
- 對象在進(jìn)行網(wǎng)絡(luò)傳輸(比如遠(yuǎn)程方法調(diào)用 RPC 的時(shí)候)之前需要先被序列化,接收到序列化的對象之后需要再進(jìn)行反序列化;
- 將對象存儲(chǔ)到文件之前需要進(jìn)行序列化,將對象從文件中讀取出來需要進(jìn)行反序列化;
- 將對象存儲(chǔ)到數(shù)據(jù)庫(如 Redis)之前需要用到序列化,將對象從緩存數(shù)據(jù)庫中讀取出來需要反序列化;
- 將對象存儲(chǔ)到內(nèi)存之前需要進(jìn)行序列化,從內(nèi)存中讀取出來之后需要進(jìn)行反序列化。
需要讓某個(gè)對象支持序列化機(jī)制,需要保證該類是可序列化的:
該類必須實(shí)現(xiàn)以下兩個(gè)接口之一:
- Serializable(優(yōu)先選擇)
- Externalizable
序列化演示:
Dog類:
// Dog類需要實(shí)現(xiàn)Serializable接口才可以支持序列化操作 class Dog implements Serializable { private String name; private int age; public Dog(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Dog{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
/** * ObjectOutputStream進(jìn)行序列化 */ @Test public void Out() throws IOException { String filePath = "D:\\data.dat"; ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath)); oos.write(100); oos.writeBoolean(true); oos.writeChar('a'); oos.writeDouble(5.21); oos.writeUTF("IMUSTCTF"); oos.writeObject(new Dog("旺財(cái)",1)); oos.close(); System.out.println("數(shù)據(jù)序列化成功!"); }
反序列化演示:
反序列化類:
/** * ObjectInputStream反序列化 */ @Test public void Input() throws IOException, ClassNotFoundException { String filePath = "D:\\data.dat"; ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath)); // 開始讀取bat文件 // 注意:讀取順序要和序列化時(shí)的順序一致! System.out.println(ois.readInt()); System.out.println(ois.readBoolean()); System.out.println(ois.readChar()); System.out.println(ois.readDouble()); System.out.println(ois.readUTF()); Object dog = ois.readObject(); System.out.println(dog); // 訪問dog的私有屬性 Dog dd = (Dog) dog; System.out.println(dd.getName()); // 關(guān)閉外層流 ois.close(); }
對象處理流使用細(xì)節(jié):
- 請按照序列化的順序進(jìn)行反序列化
- 序列化的類中建議添加如下語句:(為了提高版本的兼容性)
@Serial private static final long serialVersionUID = 1L;
序列化具有可繼承性,父類實(shí)現(xiàn)了序列化,則其子類也會(huì)默認(rèn)實(shí)現(xiàn)序列化
序列化對象時(shí),static和transient修飾的成員不會(huì)被序列化
到此這篇關(guān)于一文帶你解讀Java序列化和反序列化機(jī)制的文章就介紹到這了,更多相關(guān)Java序列化 反序列化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java之TreeUtils生成一切對象樹形結(jié)構(gòu)案例
這篇文章主要介紹了java之TreeUtils生成一切對象樹形結(jié)構(gòu)案例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09Java多線程提交按照時(shí)間順序獲取線程結(jié)果詳解流程
在工作中是否存在這樣的場景,多個(gè)線程提交執(zhí)行,你不想全部線程執(zhí)行結(jié)束了獲取結(jié)果,而是有線程完成返回結(jié)果就獲取消費(fèi)。本文提供該場景的工具類,可以直接用哦2021-11-11Java中FTPClient上傳中文目錄、中文文件名亂碼問題解決方法
這篇文章主要介紹了Java中FTPClient上傳中文目錄、中文文件名亂碼問題解決方法,本文使用apache-commons-net工具包時(shí)遇到這個(gè)問題,解決方法很簡單,需要的朋友可以參考下2015-05-05解決RabbitMq消息隊(duì)列Qos?Prefetch消息堵塞問題
這篇文章主要為大家介紹了關(guān)于如何解決解決RabbitMq?Qos?Prefetch消息堵塞的問題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-01-01java算法之靜態(tài)內(nèi)部類實(shí)現(xiàn)雪花算法
這篇文章主要介紹了java算法之靜態(tài)內(nèi)部類實(shí)現(xiàn)雪花算法,對算法感興趣的同學(xué),一定要看一下2021-05-05Spring-boot結(jié)合Shrio實(shí)現(xiàn)JWT的方法
這篇文章主要介紹了Spring-boot結(jié)合Shrio實(shí)現(xiàn)JWT的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05