Java中序列化與反序列化的定義及代碼示例
序列化與反序列化的定義
序列化(Serialization)與反序列化(Deserialization)是編程中常見的兩個概念,它們主要涉及到將數(shù)據(jù)結構或對象狀態(tài)轉換為可以存儲或傳輸?shù)母袷?,以及將存儲或傳輸?shù)母袷睫D換回原始的數(shù)據(jù)結構或對象狀態(tài)的過程。
這兩個過程在數(shù)據(jù)持久化、網(wǎng)絡通信、對象深拷貝等多個場景中發(fā)揮著重要作用。
序列化(Serialization)
序列化是指將數(shù)據(jù)結構或對象狀態(tài)轉換成可以存儲或傳輸?shù)母袷降倪^程。這個格式通常是平臺無關的,比如JSON、XML、二進制格式等,以便可以在不同的系統(tǒng)或環(huán)境中進行交換。序列化后的數(shù)據(jù)可以存儲在文件中,或者通過網(wǎng)絡發(fā)送給其他系統(tǒng)。
為什么需要序列化?
- 數(shù)據(jù)持久化:將對象狀態(tài)保存到文件中,以便在程序關閉或系統(tǒng)重啟后能夠重新加載這些數(shù)據(jù)。
- 網(wǎng)絡傳輸:在網(wǎng)絡通信中,數(shù)據(jù)需要在客戶端和服務器之間傳輸,序列化可以將對象轉換成字節(jié)流,便于在網(wǎng)絡上傳輸。
- 對象深拷貝:通過序列化一個對象,然后立即進行反序列化,可以實現(xiàn)對象的深拷貝。
反序列化(Deserialization)
反序列化是序列化的逆過程,即將序列化后的數(shù)據(jù)(如JSON、XML、二進制格式等)轉換回原始的數(shù)據(jù)結構或對象狀態(tài)。這個過程允許程序在需要時重新構建對象,并使用其原始數(shù)據(jù)。
為什么需要反序列化?
- 數(shù)據(jù)恢復:在程序啟動時,從文件中讀取序列化后的數(shù)據(jù),反序列化成對象,以恢復程序運行前的狀態(tài)。
- 數(shù)據(jù)接收:在網(wǎng)絡通信中,接收到的序列化數(shù)據(jù)需要被反序列化成對象,以便在本地系統(tǒng)中使用。
Java的序列化
Java序列化是指將Java對象的狀態(tài)轉換為可以保存或傳輸?shù)母袷降倪^程。Java提供了多種序列化方式,以滿足不同的需求和場景。以下是Java序列化的幾種主要方式:
1. 實現(xiàn)Serializable接口
- 特點:這是Java默認的序列化方式,通過實現(xiàn)java.io.Serializable接口來標記一個類可以被序列化。這種序列化方式是隱式的,會自動序列化所有非static和transient關鍵字修飾的成員變量。
- 使用場景:適用于大多數(shù)需要序列化的場景,特別是當對象的狀態(tài)需要被持久化或在網(wǎng)絡間傳輸時。
2. 實現(xiàn)Externalizable接口
- 特點:與Serializable接口類似,但Externalizable接口提供了更高的靈活性。實現(xiàn)該接口的類必須手動實現(xiàn)writeExternal()和readExternal()方法,以控制序列化和反序列化的過程。
- 使用場景:適用于需要精確控制序列化過程的場景,比如只序列化對象的某些部分,或者需要對序列化數(shù)據(jù)進行加密等。
3. 使用JSON序列化庫
- 常用庫:如Jackson、Gson等。
- 特點:將對象轉換為JSON格式的字符串進行序列化,可以跨語言、跨平臺進行數(shù)據(jù)交換。JSON格式易于閱讀和編寫,也易于機器解析和生成。
- 使用場景:適用于需要與其他語言或系統(tǒng)交互的場景,或者當對象需要被存儲為文本格式時。
4. 使用XML序列化庫
- 常用庫:如JAXB、XStream等。
- 特點:將對象轉換為XML格式的字符串進行序列化,同樣可以跨語言、跨平臺進行數(shù)據(jù)交換。XML格式具有良好的可擴展性和可讀性。
- 使用場景:適用于需要遵循特定XML標準的場景,或者當對象需要被存儲為易于人類閱讀的格式時。
5. 使用二進制序列化庫
- 常用庫:如Protocol Buffers(protobuf)、Apache Thrift、Apache Avro等。
- 特點:將對象序列化為二進制格式進行傳輸和存儲,效率較高。這些庫通常提供了豐富的數(shù)據(jù)結構和高效的編碼解碼算法。
- 使用場景:適用于對性能要求較高的場景,比如需要頻繁序列化和反序列化大量數(shù)據(jù)的系統(tǒng)。
6. 其他序列化方式
- Hessian序列化:Hessian是一種通過網(wǎng)絡傳輸和存儲Java對象的二進制格式,可以跨語言、跨平臺使用,效率較高。
- Kryo序列化:Kryo是一種高性能的Java序列化庫,序列化和反序列化速度都很快,但只能用于Java環(huán)境。
Java提供了多種序列化方式,每種方式都有其特點和適用場景。在實際應用中,可以根據(jù)具體需求和場景選擇合適的方式進行Java對象的序列化。需要注意的是,除了Java默認的序列化方式外,其他方式通常需要引入相應的第三方庫。
Java默認序列化與反序列化示例
我們先將一些Java的變量和一個Car對象序列化到 d盤的一個名為 data.dat 的文件中。
/**
* ObjectOutputStream 的使用,完成數(shù)據(jù)的序列化
* ObjectOutputStream 是序列化
*/
public class ObjectOutputStreamDemo {
public static void main(String[] args) throws IOException {
//序列化后,保存到文本格式不是純文本txt,而是按照它的格式來保存
String filePath = "d:\\data.dat";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
oos.writeInt(100);//int -> Integer(實現(xiàn)了Serializable)
oos.writeBoolean(true);//boolean -> Boolean(實現(xiàn)了 Serializable)
oos.writeChar('o');//char -> Character(實現(xiàn)了Serializable)
oos.writeDouble(4.4);//double -> Double(實現(xiàn)了 Serializable)
oos.writeUTF("對象輸出流");//String (實現(xiàn)了Serializable)
oos.writeObject(new Car("xiaomi su7","Pro","Gulf Blue","300,000"));
oos.close();
System.out.println("數(shù)據(jù)以序列化的形式保存完成");
/*
如果Car沒有實現(xiàn) Serializable接口,會報錯如下:
Exception in thread "main" java.io.NotSerializableException: org.example.io.demo.lession20.Car
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at org.example.io.demo.lession20.ObjectOutputStreamDemo.main(ObjectOutputStreamDemo.java:24)
*/
}
}
@Data
class Car implements Serializable {
private String name;
private String type;
private static String color ;
private transient String price ;
public Car(String name,String type,String color,String price){
this.name = name;
this.type = type;
this.color = color;
this.price = price;
}
}
執(zhí)行main方法后,會在d盤根目錄下看到一個 data.dat的文件。

使用記事本打開,依稀可以看到點什么,但明顯不是txt格式的文本。

下面我們將這個文件反序列化至程序中并打印出來:
/**
* 讀取序列化文件,并通過反序列化恢復數(shù)據(jù)
* ObjectInputStream 是反序列化
*/
public class ObjectInputStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//指定反序列化的文件
String filePath = "d:\\data.dat";
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
//讀?。捶葱蛄谢┑捻樞蛐枰捅4鏀?shù)據(jù)(即序列化)的順序一致,否則會有異常
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());
System.out.println(ois.readObject().toString());
ois.close();
}
}
輸出結果為:
100
true
o
4.4
對象輸出流
Car(name=xiaomi su7, type=Pro, price=null)
Java 序列化與反序列化注意事項:
- 讀寫順序要一致。
- 序列化與反序列化對象要實現(xiàn) Serializable 接口。
- 序列化中的類中,建議添加SerialVersionUID,為了提高版本的兼容性。
- 序列化對象時,默認將里面所有的屬性都進行序列化,除了stati、transient 修飾的成員。
- 序列化對象時,要求里面屬性的類型也需要實現(xiàn)序列化接口。
- 序列化具備可繼承性,也就是如果某類已經(jīng)實現(xiàn)了序列化,則它的所有子類也默認實現(xiàn)了序列化。
TIPS:static 和 transient 在序列化中的區(qū)別
static關鍵字
- 定義:static關鍵字用于修飾類的成員變量和方法,使其成為類變量或類方法,而不是實例變量或實例方法。類變量屬于類本身,而非類的任何特定實例。
- 序列化行為:在序列化過程中,被static修飾的變量(即類變量)不會被序列化。這是因為static變量是類級別的,它們不屬于任何特定的對象實例,而是由所有實例共享。因此,序列化一個對象時,不會包含其類變量的值,因為類變量的值在JVM中是全局的,與特定的序列化實例無關。
- 反序列化影響:反序列化一個對象時,被static修飾的變量會保持其在JVM中的當前值,而不是從序列化數(shù)據(jù)中恢復。這是因為靜態(tài)變量是全局的,不受單個對象實例的序列化/反序列化過程影響。
transient關鍵字
- 定義:transient關鍵字用于修飾類的成員變量,以指示該變量在序列化時不應被序列化。
- 序列化行為:當一個對象被序列化時,所有非transient修飾的成員變量都會被序列化,而transient修飾的變量則會被忽略。這意味著,在序列化后的數(shù)據(jù)中,不會包含任何被transient修飾的變量的值。
- 反序列化影響:在反序列化過程中,被transient修飾的變量將不會被恢復其序列化前的值。相反,它們會被初始化為默認值(例如,數(shù)值類型的變量會被初始化為0或false,對象類型的變量會被初始化為null)。因此,開發(fā)者需要在反序列化后,根據(jù)需要手動為這些變量賦值。
二者對比表格
| 關鍵字 | 定義 | 序列化行為 | 反序列化影響 |
|---|---|---|---|
| static | 修飾類變量或類方法,屬于類本身 | 不被序列化 | 保持JVM中的當前值 |
| transient | 修飾成員變量,指示在序列化時忽略該變量 | 被忽略,不被序列化 | 被初始化為默認值 |
總結
到此這篇關于Java中序列化與反序列化的文章就介紹到這了,更多相關Java序列化與反序列化內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot如何使用mail實現(xiàn)登錄郵箱驗證
在實際的開發(fā)當中,不少的場景中需要我們使用更加安全的認證方式,同時也為了防止一些用戶惡意注冊,我們可能會需要用戶使用一些可以證明個人身份的注冊方式,如短信驗證、郵箱驗證等,這篇文章主要介紹了SpringBoot如何使用mail實現(xiàn)登錄郵箱驗證,需要的朋友可以參考下2024-06-06
解決springboot遇到autowire注入為null的問題
這篇文章主要介紹了解決springboot遇到autowire注入為null的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03
Eclipse創(chuàng)建JavaWeb工程的完整步驟記錄
很多新手不知道Eclipse怎么創(chuàng)建Java Web項目,一起來看看吧,這篇文章主要給大家介紹了關于Eclipse創(chuàng)建JavaWeb工程的完整步驟,需要的朋友可以參考下2023-10-10
Java超詳細教你寫一個網(wǎng)絡購書系統(tǒng)案例
這篇文章主要介紹了怎么用Java來寫一個購書系統(tǒng),購買書籍主要需要每本書的編號、書名、單價、庫存屬性,能夠讓客戶通過編號來選書,感興趣的朋友跟隨文章往下看看吧2022-03-03
如何基于SpringMVC實現(xiàn)斷點續(xù)傳(HTTP)
這篇文章主要介紹了如何基于SpringMVC實現(xiàn)斷點續(xù)傳(HTTP),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-01-01

