最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中對象的轉(zhuǎn)移之序列化與反序列化方式

 更新時間:2026年05月18日 10:17:12   作者:ktkiko11  
文章介紹了序列化與反序列化的定義和實現(xiàn)流程,重點闡述了Java中的序列化與反序列化實現(xiàn),包括Serializable接口、Externalizable接口、transient關(guān)鍵字等,并指出了Java原生序列化的缺點及替代方案FastJson和Protobuf,最終總結(jié)了選擇不同序列化工具的場景和優(yōu)勢

1. 序列化與反序列化的定義與實現(xiàn)流程

序列化(Serialization)反序列化(Deserialization)是處理對象持久化和網(wǎng)絡(luò)傳輸?shù)年P(guān)鍵技術(shù)。它們在分布式系統(tǒng)、緩存系統(tǒng)和跨應(yīng)用傳輸數(shù)據(jù)中應(yīng)用廣泛。

序列化是什么?

序列化是將一個對象轉(zhuǎn)換成字節(jié)流的過程,這樣的數(shù)據(jù)形式便于存儲到文件、數(shù)據(jù)庫,或通過網(wǎng)絡(luò)傳輸?shù)狡渌到y(tǒng)。簡單來說,序列化就是把數(shù)據(jù)打包成一個可轉(zhuǎn)移、存儲的“快遞包裹”。

反序列化是什么?

反序列化是序列化的逆過程,即將字節(jié)流還原為對象的過程。通過反序列化,系統(tǒng)可以讀取存儲的對象數(shù)據(jù),或通過網(wǎng)絡(luò)傳輸接收到的數(shù)據(jù)重構(gòu)出對象。

序列化的實現(xiàn)流程

序列化和反序列化的基本流程可以分為以下幾步:

對象狀態(tài)轉(zhuǎn)換為字節(jié)流

  • 將對象中的屬性、數(shù)據(jù)結(jié)構(gòu)和標(biāo)識符等信息轉(zhuǎn)換成一組字節(jié),形成一個流。
  • 這個流包含了該對象的類信息以及它的字段值,使得接收方能夠準(zhǔn)確地還原對象。

傳輸或存儲字節(jié)流

  • 將得到的字節(jié)流傳輸?shù)侥繕?biāo)位置(例如:遠(yuǎn)程服務(wù)器)或存儲到介質(zhì)中(如文件系統(tǒng)、數(shù)據(jù)庫),以便后續(xù)的訪問或復(fù)用。

將字節(jié)流轉(zhuǎn)為對象(反序列化)

  • 當(dāng)需要讀取對象時,字節(jié)流會被重新轉(zhuǎn)換回對象,這時會從流中解析出類信息及字段數(shù)據(jù),恢復(fù)對象的完整狀態(tài)。

這種流程實現(xiàn)了對象在不同系統(tǒng)、不同時刻的持久化保存和跨網(wǎng)絡(luò)、跨進(jìn)程的數(shù)據(jù)傳輸。序列化的技術(shù)不僅限于Java,在很多語言和框架中都有類似實現(xiàn),適用于不同的應(yīng)用需求。

2. Java中的序列化與反序列化實現(xiàn)

Java 提供了內(nèi)置的序列化工具,使對象能方便地轉(zhuǎn)換為字節(jié)流。主要工具包括ObjectOutputStreamObjectInputStream,以及SerializableExternalizable接口。

1.Serializable接口:標(biāo)識對象可序列化

要實現(xiàn)序列化的對象類需要實現(xiàn)Serializable接口。這是一個標(biāo)記接口,也就是不包含方法,只是標(biāo)記該類可以序列化。

示例

import java.io.Serializable;

public class Person implements Serializable {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 省略getters和setters
}

解釋: 在這個例子中,Person類實現(xiàn)了Serializable接口,說明可以把Person對象轉(zhuǎn)成字節(jié)流。類中包含的所有字段都會在序列化過程中轉(zhuǎn)換成字節(jié)流。

2.ObjectOutputStream和ObjectInputStream:讀寫字節(jié)流的對象

  • ObjectOutputStream:用來寫入對象的字節(jié)流,執(zhí)行序列化。
  • ObjectInputStream:用來讀取對象的字節(jié)流,執(zhí)行反序列化。

示例:序列化對象

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

public class SerializeExample {
    public static void main(String[] args) {
        Person person = new Person("Alice", 30);

        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"))) {
            oos.writeObject(person); // 將Person對象寫入文件
            System.out.println("對象已序列化");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

解釋

  1. 創(chuàng)建ObjectOutputStream,用于將對象寫入文件。
  2. 使用writeObject方法將person對象轉(zhuǎn)為字節(jié)流寫入文件person.ser中。
  3. 文件中保存了person對象的狀態(tài)數(shù)據(jù),以便后續(xù)讀取。

示例:反序列化對象

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class DeserializeExample {
    public static void main(String[] args) {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) {
            Person person = (Person) ois.readObject(); // 從文件中讀取對象
            System.out.println("對象已反序列化: " + person.getName() + ", " + person.getAge());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

解釋

  1. 創(chuàng)建ObjectInputStream,讀取存儲的字節(jié)流。
  2. 使用readObject方法從字節(jié)流中還原對象。
  3. 將反序列化的person對象信息打印出來。

3.transient關(guān)鍵字:保護(hù)敏感數(shù)據(jù)

在某些場景中,可能不希望某些字段被序列化,例如密碼、敏感信息等。可以用transient關(guān)鍵字聲明這些字段,以忽略序列化。

示例

public class User implements Serializable {
    private String username;
    private transient String password; // 不會被序列化

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }
}

在這個例子中,password字段不會被序列化,也不會被寫入字節(jié)流中,從而保護(hù)了敏感數(shù)據(jù)。

4.Externalizable接口:自定義序列化邏輯

除了Serializable,Java還提供了Externalizable接口,允許完全自定義序列化過程。實現(xiàn)Externalizable接口的類需要覆蓋兩個方法:

  • writeExternal(ObjectOutput out):定義如何序列化對象。
  • readExternal(ObjectInput in):定義如何反序列化對象。

示例

import java.io.Externalizable;
import java.io.ObjectOutput;
import java.io.ObjectInput;

public class Book implements Externalizable {
    private String title;
    private double price;

    public Book() {} // 必須有無參構(gòu)造方法

    public Book(String title, double price) {
        this.title = title;
        this.price = price;
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeUTF(title);
        out.writeDouble(price);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        title = in.readUTF();
        price = in.readDouble();
    }
}

解釋

  • writeExternal方法中定義了如何把titleprice字段寫入字節(jié)流。
  • readExternal方法中定義了從字節(jié)流讀取數(shù)據(jù)的順序和方式。
  • 這種方式比Serializable更靈活,可以完全控制序列化的細(xì)節(jié)。

在Java中,序列化和反序列化的基本實現(xiàn)方式非常直接,Serializable接口和ObjectOutputStream/ObjectInputStream提供了便捷的工具。對于更復(fù)雜的需求,Externalizable接口可以讓開發(fā)者自定義序列化和反序列化的過程。這些方法不僅在Java內(nèi)使用方便,同時為跨網(wǎng)絡(luò)傳輸、存儲等應(yīng)用場景提供了基礎(chǔ)支持。

3. Java序列化的缺點和替代方案

Java原生序列化是一種方便的方式,特別適合在同一系統(tǒng)中使用。不過,它在實際應(yīng)用中存在以下明顯的缺點:

Java序列化的缺點

性能較差

  • Java序列化默認(rèn)包含了很多額外的元數(shù)據(jù)(比如類信息),導(dǎo)致生成的字節(jié)流文件偏大。序列化和反序列化速度較慢,尤其在大規(guī)模數(shù)據(jù)傳輸中更明顯。
  • 這種速度較慢的序列化方式在處理大量數(shù)據(jù)、需要頻繁傳輸?shù)姆植际较到y(tǒng)中效率不足。

不跨語言

  • Java原生序列化生成的二進(jìn)制格式只適用于Java平臺。也就是說,其他編程語言無法直接解析Java序列化生成的字節(jié)流。因此,如果系統(tǒng)需要與其他語言(例如C++、Python)交互,就不適用Java原生序列化。

存在安全漏洞

  • Java序列化容易受到“反序列化攻擊”的威脅。惡意用戶可以構(gòu)造特定的序列化數(shù)據(jù)流,在反序列化過程中觸發(fā)惡意代碼執(zhí)行。這種攻擊常見于接受外部輸入的系統(tǒng),安全風(fēng)險很大。
  • 由于這種安全隱患,Java原生序列化通常不適合在公開的API或網(wǎng)絡(luò)傳輸中使用。

缺乏版本控制

  • 當(dāng)類的結(jié)構(gòu)發(fā)生改變(例如添加或移除字段)時,Java的序列化和反序列化很容易出現(xiàn)兼容性問題。例如,老版本的對象在字段缺失時可能導(dǎo)致反序列化失敗。
  • 盡管可以通過serialVersionUID標(biāo)識版本,但在實際應(yīng)用中維護(hù)起來仍然較麻煩。

這些缺點在很多分布式、跨平臺系統(tǒng)中都是阻礙,因此現(xiàn)在很多開發(fā)者會考慮使用更高效、安全、靈活的序列化框架。下面介紹兩個主流替代方案:FastJsonProtobuf。

替代方案一:FastJson

FastJson是阿里巴巴開發(fā)的一個高性能JSON庫,主要用于Java對象和JSON格式之間的相互轉(zhuǎn)換。JSON格式是一種人類可讀的數(shù)據(jù)格式,可以方便地在不同語言間共享。

FastJson的優(yōu)勢

跨平臺

  • JSON是一種輕量級的數(shù)據(jù)交換格式,幾乎每種編程語言都支持。因此,使用FastJson序列化的對象能夠輕松地在不同編程語言之間傳遞。

速度快,性能優(yōu)異

  • FastJson專為速度和性能優(yōu)化,在Java中使用非常高效。它支持流式解析、緩存等多種優(yōu)化方式,在大數(shù)據(jù)量處理上比Java原生序列化性能更佳。

支持靈活的數(shù)據(jù)結(jié)構(gòu)

  • FastJson序列化的數(shù)據(jù)格式(JSON)具有良好的兼容性,特別適合于動態(tài)數(shù)據(jù)結(jié)構(gòu)和頻繁變化的數(shù)據(jù)格式。即便類的結(jié)構(gòu)發(fā)生變化,JSON也不會導(dǎo)致反序列化失敗,因為可以通過字段名來匹配數(shù)據(jù)。

安全性更高

  • JSON格式天然安全,不會引發(fā)Java序列化中的反序列化漏洞。同時FastJson提供了對各種對象類型的安全處理機制,能過濾不安全的類型,進(jìn)一步保障系統(tǒng)安全。

FastJson使用示例

import com.alibaba.fastjson.JSON;

public class FastJsonExample {
    public static void main(String[] args) {
        // 序列化
        Person person = new Person("Alice", 25);
        String jsonString = JSON.toJSONString(person);
        System.out.println("序列化為JSON字符串:" + jsonString);

        // 反序列化
        Person deserializedPerson = JSON.parseObject(jsonString, Person.class);
        System.out.println("反序列化對象:" + deserializedPerson.getName());
    }
}

替代方案二:Protobuf

Protobuf(Protocol Buffers)是由Google推出的一種序列化框架,專門用于跨語言、跨平臺的高效數(shù)據(jù)序列化。

Protobuf的優(yōu)勢

高效的二進(jìn)制格式

  • Protobuf會將對象數(shù)據(jù)序列化成緊湊的二進(jìn)制格式,占用的空間遠(yuǎn)小于JSON或Java原生序列化生成的數(shù)據(jù)。
  • 序列化和反序列化速度極快,非常適合在網(wǎng)絡(luò)傳輸和高頻讀寫場景下使用。

跨語言

  • Protobuf支持多種編程語言(如Java、Python、C++等),可以在不同平臺之間無縫共享數(shù)據(jù)。這是Protobuf在分布式系統(tǒng)中被廣泛采用的重要原因。

支持嚴(yán)格的版本控制

  • Protobuf的“消息結(jié)構(gòu)”定義文件可以兼容新舊版本,當(dāng)數(shù)據(jù)結(jié)構(gòu)發(fā)生變化時,Protobuf可以自動適應(yīng)新舊字段,極大減少了版本兼容問題。

安全性強

  • Protobuf的格式是結(jié)構(gòu)化的,因此不易受到反序列化攻擊。數(shù)據(jù)結(jié)構(gòu)和解析過程非常明確,使用起來更安全。

Protobuf使用示例: Protobuf使用時,需要先定義一個.proto文件,指定數(shù)據(jù)結(jié)構(gòu):

// person.proto
syntax = "proto3";

message Person {
    string name = 1;
    int32 age = 2;
}

然后,通過Protobuf編譯工具生成對應(yīng)的Java類,進(jìn)行序列化和反序列化:

Person person = Person.newBuilder().setName("Alice").setAge(25).build();
byte[] data = person.toByteArray(); // 序列化
Person deserializedPerson = Person.parseFrom(data); // 反序列化

在實際項目中,由于Java原生序列化的性能、安全和跨語言問題,開發(fā)者更傾向于選擇FastJson或Protobuf。FastJson適合數(shù)據(jù)格式簡單、語言可讀性要求高的應(yīng)用場景;Protobuf則適合大數(shù)據(jù)傳輸、分布式和跨平臺應(yīng)用中對效率和兼容性要求高的場景。兩者都比Java原生序列化更靈活、安全和高效。

4. 總結(jié)

序列化與反序列化是現(xiàn)代軟件開發(fā)中用于數(shù)據(jù)傳輸、存儲的基本技術(shù),尤其在分布式系統(tǒng)、緩存系統(tǒng)和跨語言數(shù)據(jù)交換中應(yīng)用廣泛。通過這些技術(shù),可以將復(fù)雜的對象在不同進(jìn)程、系統(tǒng)甚至平臺間傳遞和共享。

1. Java原生序列化的基礎(chǔ)

Java為對象序列化提供了內(nèi)置支持,使用Serializable接口和ObjectOutputStream/ObjectInputStream流實現(xiàn)簡單直接的序列化。Java原生序列化的流程包括:

  • 將對象及其字段數(shù)據(jù)轉(zhuǎn)化為字節(jié)流,保存或傳輸。
  • 在需要時通過字節(jié)流反序列化為對象,恢復(fù)對象狀態(tài)。

這種方式在同一Java系統(tǒng)內(nèi)部傳輸數(shù)據(jù)非常便捷,但存在性能、安全和兼容性等問題。

2. Java原生序列化的缺點

Java原生序列化適用于小規(guī)模數(shù)據(jù)傳輸或非跨平臺的Java系統(tǒng)。但在生產(chǎn)級別應(yīng)用中,它的缺陷較為明顯:

  • 性能低:字節(jié)流數(shù)據(jù)體積大,序列化和反序列化速度相對較慢。
  • 不跨語言:生成的字節(jié)流只能在Java環(huán)境中解析,無法直接用于與其他語言的交互。
  • 安全性欠佳:存在反序列化漏洞風(fēng)險,容易受到反序列化攻擊。

因此,Java原生序列化適合臨時數(shù)據(jù)保存,但在涉及敏感數(shù)據(jù)和跨系統(tǒng)場景時,存在較大風(fēng)險。

3. 替代方案:FastJson和Protobuf

為了解決Java原生序列化的不足,許多開發(fā)者選擇更高效的序列化框架,例如FastJson和Protobuf:

  • FastJson:適合JSON格式的數(shù)據(jù)交換,提供跨平臺、通用的人類可讀格式。其序列化過程速度快,兼容性好,非常適合在前后端通信和跨平臺輕量級數(shù)據(jù)傳輸中使用。

  • Protobuf:適合分布式系統(tǒng)、大數(shù)據(jù)和高效跨平臺傳輸。Protobuf的二進(jìn)制格式占用空間小,解析速度快,版本控制友好,是數(shù)據(jù)高效傳輸?shù)睦硐脒x擇,尤其在微服務(wù)和多語言系統(tǒng)中應(yīng)用廣泛。

使用場景總結(jié)

  • 選擇Java原生序列化:適合在同一Java應(yīng)用內(nèi)的數(shù)據(jù)存儲(如緩存、簡單對象的臨時保存),對性能和跨平臺要求不高的情況下。
  • 選擇FastJson:適合需要將數(shù)據(jù)轉(zhuǎn)化為人類可讀格式且在前后端或不同系統(tǒng)中共享時,JSON格式兼容性強且更便于調(diào)試。
  • 選擇Protobuf:適合大型、復(fù)雜的分布式系統(tǒng)和跨語言數(shù)據(jù)傳輸,對性能和傳輸效率要求高的情況。

綜上所述,序列化和反序列化技術(shù)的發(fā)展,為現(xiàn)代軟件提供了多樣化的數(shù)據(jù)傳輸和持久化方案。通過合理選擇合適的序列化工具,可以優(yōu)化系統(tǒng)的性能、安全性和兼容性,從而滿足不同應(yīng)用的需求。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot中實現(xiàn)JWT登錄授權(quán)+無感刷新全流程

    SpringBoot中實現(xiàn)JWT登錄授權(quán)+無感刷新全流程

    在當(dāng)今的分布式系統(tǒng)和前后端分離架構(gòu)盛行的時代,傳統(tǒng)的基于?Session?的認(rèn)證方式逐漸暴露出諸多弊端,而?JWT的出現(xiàn),猶如一道曙光,為這些問題提供了完美的解決方案,本文將詳細(xì)地為大家講解?Spring?Boot?整合?JWT?實現(xiàn)登錄認(rèn)證與接口授權(quán)的全流程
    2026-04-04
  • idea設(shè)置在包里面在創(chuàng)建一個包方式

    idea設(shè)置在包里面在創(chuàng)建一個包方式

    這篇文章主要介紹了idea設(shè)置在包里面在創(chuàng)建一個包方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • springboot+EHcache 實現(xiàn)文章瀏覽量的緩存和超時更新

    springboot+EHcache 實現(xiàn)文章瀏覽量的緩存和超時更新

    這篇文章主要介紹了springboot+EHcache 實現(xiàn)文章瀏覽量的緩存和超時更新,問題描述和解決思路給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2017-04-04
  • java如何上傳文件到sftp服務(wù)器

    java如何上傳文件到sftp服務(wù)器

    本文主要講述了如何使用JSch庫將數(shù)據(jù)文件上傳到SFTP服務(wù)器,并分享了過程中遇到的一些坑,例如目錄創(chuàng)建、文件刪除等問題,以及如何使用SFTP通道執(zhí)行命令、文件上傳等操作,通過本文,讀者可以了解SFTP上傳文件的基本步驟和注意事項,同時也提供了一些解決方法
    2026-04-04
  • 使用JAVA判斷凸多邊形的示例代碼

    使用JAVA判斷凸多邊形的示例代碼

    本文提供了使用JAVA判斷凸多邊形的示例代碼供大家參考學(xué)習(xí),需要的朋友可以看一下
    2013-11-11
  • Java?IO篇之Reactor?網(wǎng)絡(luò)模型的概念

    Java?IO篇之Reactor?網(wǎng)絡(luò)模型的概念

    Reactor?模式也叫做反應(yīng)器設(shè)計模式,是一種為處理服務(wù)請求并發(fā)提交到一個或者多個服務(wù)處理器的事件設(shè)計模式,Reactor?模式主要由?Reactor?和處理器?Handler?這兩個核心部分組成,本文給大家介紹Java?IO篇之Reactor?網(wǎng)絡(luò)模型的概念,感興趣的朋友一起看看吧
    2022-01-01
  • 淺談一下Java中的堆和棧

    淺談一下Java中的堆和棧

    這篇文章主要介紹了一下Java中的堆和棧,Java數(shù)據(jù)類型在執(zhí)行過程中存儲在兩種不同形式的內(nèi)存中:棧和堆,它們通常由運行Java虛擬機(JVM)的底層平臺維護(hù),需要的朋友可以參考下
    2023-04-04
  • jstack報錯Unable to open socket file解決

    jstack報錯Unable to open socket file解決

    這篇文章主要為大家介紹了jstack報錯Unable to open socket file的解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-02-02
  • Java中json使用方法_動力節(jié)點Java學(xué)院整理

    Java中json使用方法_動力節(jié)點Java學(xué)院整理

    JSON(JavaScript Object Notation) 是一種輕量級的數(shù)據(jù)交換格式, json是個非常重要的數(shù)據(jù)結(jié)構(gòu),在web開發(fā)中應(yīng)用十分廣泛。下面通過本文給大家講解Java中json使用方法,感興趣的朋友一起看看吧
    2017-07-07
  • Java解析XML文件開源庫DOM4J

    Java解析XML文件開源庫DOM4J

    dom4j是一個Java的XML API,是jdom的升級品,用來讀寫XML文件的。dom4j是一個十分優(yōu)秀的JavaXML API,具有性能優(yōu)異、功能強大和極其易使用的特點,它的性能超過sun公司官方的dom技術(shù),同時它也是一個開放源代碼的軟件
    2023-01-01

最新評論

梁平县| 卢氏县| 基隆市| 甘谷县| 莲花县| 张家口市| 新乡市| 萨嘎县| 壶关县| 江源县| 龙口市| 蓬安县| 凤凰县| 江油市| 北川| 辽宁省| 禄劝| 册亨县| 迁西县| 林甸县| 安义县| 齐齐哈尔市| 赞皇县| 乌拉特后旗| 绩溪县| 额敏县| 沅陵县| 新安县| 桦甸市| 酉阳| 分宜县| 庆阳市| 建湖县| 托克托县| 郯城县| 黎平县| 门头沟区| 股票| 芦溪县| 衡阳县| 兴隆县|