亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java中序列化與反序列化的特性解讀

 更新時間:2023年08月10日 09:21:27   作者:ycfxhsw  
這篇文章主要介紹了Java中序列化與反序列化的特性解讀,當(dāng)我們需要將內(nèi)存中的對象持久化到磁盤,數(shù)據(jù)庫中時, 當(dāng)我們需要與瀏覽器進(jìn)行交互時,當(dāng)我們需要實現(xiàn) RPC 時, 這個時候就需要序列化和反序列化了,需要的朋友可以參考下

一、序列化與反序列化

  • 序列化:把對象轉(zhuǎn)換為字節(jié)序列的過程稱為對象的序列化。
  • 反序列化:把字節(jié)序列恢復(fù)為對象的過程稱為對象的反序列化。

二、什么時候需要用到序列化和反序列化

當(dāng)我們只在本地 JVM 里運行下 Java 實例,這個時候是不需要什么序列化和反序列化的,但當(dāng)我們需要將內(nèi)存中的對象持久化到磁盤,數(shù)據(jù)庫中時, 當(dāng)我們需要與瀏覽器進(jìn)行交互時,當(dāng)我們需要實現(xiàn) RPC 時, 這個時候就需要序列化和反序列化了。

前兩個需要用到序列化和反序列化的場景, 是不是讓我們有一個很大的疑問? 我們在與瀏覽器交互時,還有將內(nèi)存中的對象持久化到數(shù)據(jù)庫中時,好像都沒有去進(jìn)行序列化和反序列化, 因為我們都沒有實現(xiàn) Serializable 接口, 但一直正常運行。

下面先給出結(jié)論:

只要我們對內(nèi)存中的對象進(jìn)行持久化或網(wǎng)絡(luò)傳輸, 這個時候都需要序列化和反序列化.

理由:

服務(wù)器與瀏覽器交互時真的沒有用到 Serializable 接口嗎?JSON 格式實際上就是將一個對象轉(zhuǎn)化為字符串, 所以服務(wù)器與瀏覽器交互時的數(shù)據(jù)格式其實是字符串,我們來看來 String 類型的源碼:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
    /** Cache the hash code for the string */
    private int hash; // Default to 0
    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -6849794470754667710L;

String 類型實現(xiàn)了 Serializable 接口,并顯示指定 serialVersionUID 的值.

然后我們再來看對象持久化到數(shù)據(jù)庫中時的情況, Mybatis 數(shù)據(jù)庫映射文件里的 insert 代碼:

<insert id="insertUser" parameterType="com.ycfxhsw.User">
    INSERT INTO t_user(name, age) VALUES (#{name}, #{age})
</insert>

實際上我們并不是將整個對象持久化到數(shù)據(jù)庫中, 而是將對象中的屬性持久化到數(shù)據(jù)庫中, 而這些屬性都是實現(xiàn)了 Serializable 接口的基本屬性.

三、為什么要實現(xiàn) Serializable 接口?

在 Java 中實現(xiàn)了 Serializable 接口后, JVM 會在底層幫我們實現(xiàn)序列化和反序列化, 如果我們不實現(xiàn) Serializable 接口, 那自己去寫一套序列化和反序列化代碼也行。

四、為什么還要指定 serialVersionUID 的值?

如果不顯示指定 serialVersionUID, JVM 在序列化時會根據(jù)屬性自動生成一個 serialVersionUID, 然后與屬性一起序列化,再進(jìn)行持久化或網(wǎng)絡(luò)傳輸。

在反序列化時,JVM 會再根據(jù)屬性自動生成一個新版 serialVersionUID,然后將這個新版 serialVersionUID 與序列化時生成的舊版 serialVersionUID 進(jìn)行比較,如果相同則反序列化成功, 否則報錯.

如果顯示指定了 serialVersionUID, JVM 在序列化和反序列化時仍然都會生成一個 serialVersionUID, 但值為我們顯示指定的值,這樣在反序列化時新舊版本的 serialVersionUID 就一致了.

在實際開發(fā)中, 不顯示指定 serialVersionUID 的情況會導(dǎo)致什么問題?如果我們的類寫完后不再修改,那當(dāng)然不會有問題。

但這在實際開發(fā)中是不可能的,我們的類會不斷迭代,一旦類被修改了,那舊對象反序列化就會報錯。所以在實際開發(fā)中, 我們都會顯示指定一個 serialVersionUID,值是多少無所謂, 只要不變就行。

寫個實例測試下:

(1) User 類

  • 不顯示指定 serialVersionUID.
import java.io.Serializable;
public class User implements Serializable {
    String name;
    Integer age;
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
	// 省略 get/set 方法
}

(2) 測試類

先進(jìn)行序列化, 再進(jìn)行反序列化.

public class SerializeTest {
    private static File file = new File("D:/Desktop/user.txt");
    private static void serialize(User user) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
        oos.writeObject(user);
        oos.close();
    }
    private static User deserialize() throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        return (User) ois.readObject();
    }
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        User user = new User();
        user.setName("織女");
        user.setAge(18);
        System.out.println("序列化前的結(jié)果為:" + user);
        serialize(user);
        User user1 = deserialize();
        System.out.println("反序列化后的結(jié)果為:" + user1);
    }
}

序列化前的結(jié)果為:User{name=‘織女’, age=18}

反序列化后的結(jié)果為:User{name=‘織女’, age=18}

(3) 結(jié)果

先注釋掉反序列化代碼, 執(zhí)行序列化代碼, 然后 User 類新增一個屬性 sex

public class User implements Serializable {
    String name;
    Integer age;
    String sex;
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }
	// // 省略 get/set 方法
}

再注釋掉序列化代碼執(zhí)行反序列化代碼, 最后結(jié)果如下:

local class incompatible: stream classdesc serialVersionUID = -8867211101605543804, local class serialVersionUID = 6343365699042275217

報錯結(jié)果為序列化與反序列化產(chǎn)生的 serialVersionUID 不一致。

接下來我們在上面 User 類的基礎(chǔ)上顯示指定一個 serialVersionUID

private static final long serialVersionUID = 1L;

再執(zhí)行上述步驟, 測試結(jié)果如下:

序列化前的結(jié)果為:User{name=‘織女’, age=18} 反序列化后的結(jié)果為:User{name=‘織女’, age=18, sex=‘null’}

顯示指定 serialVersionUID 后就解決了序列化與反序列化產(chǎn)生的 serialVersionUID 不一致的問題。

五、Java 序列化的其他特性

先說結(jié)論, 被 transient 關(guān)鍵字修飾的屬性不會被序列化, static 屬性也不會被序列化.

我們來測試下這個結(jié)論:

(1) User 類

public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private Integer age;
    private transient String sex;
    private static String signature = "你眼中的世界就是你自己的樣子";
    @Override
    public String toString() {
        return "User{" +
                " + name + '\\'' +
                ", age=" + age +
                ", sex='" + sex +'\\'' +
                ", signature='" + signature + '\\'' +
                '}';
    }
    // 省略 get/set 方法
}

(2) 測試類

public class SerializeTest {
    private static File file = new File("D:/Desktop/user.txt");
    private static void serialize(User user) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
        oos.writeObject(user);
        oos.close();
    }
    private static User deserialize() throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        return (User) ois.readObject();
    }
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        User user = new User();
        user.setName("織女");
        user.setAge(18);
        user.setSex("woman");
        System.out.println("序列化前的結(jié)果為:" + user);
        serialize(user);
        User user1 = deserialize();
        System.out.println("反序列化后的結(jié)果為:" + user1);
    }
}

(3) 結(jié)果

先注釋掉反序列化代碼, 執(zhí)行序列化代碼, 然后修改 User 類 signature = “我的眼里只有你”,再注釋掉序列化代碼執(zhí)行反序列化代碼, 最后結(jié)果如下:

序列化前的結(jié)果: User{name=‘織女’, age=18, sex=‘woman’, signature=‘你眼中的世界就是你自己的樣子’}

反序列化后的結(jié)果: User{name=‘織女’, age=18, sex=‘null’, signature=‘我的眼里只有你’}

六、static 屬性為什么不會被序列化?

因為序列化是針對對象而言的,而 static 屬性優(yōu)先于對象存在, 隨著類的加載而加載, 所以不會被序列化.

看到這個結(jié)論, 是不是有人會問, serialVersionUID 也被 static 修飾, 為什么 serialVersionUID 會被序列化?

其實 serialVersionUID 屬性并沒有被序列化, JVM 在序列化對象時會自動生成一個 serialVersionUID, 然后將我們顯示指定的 serialVersionUID 屬性值賦給自動生成的 serialVersionUID。

到此這篇關(guān)于Java中序列化與反序列化的特性解讀的文章就介紹到這了,更多相關(guān)Java序列化與反序列化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺談Spring Boot 屬性配置和自定義屬性配置

    淺談Spring Boot 屬性配置和自定義屬性配置

    這篇文章主要介紹了淺談Spring Boot 屬性配置和自定義屬性配置,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • 一文解決pom.xml報錯Dependency "xxx" not found的問題

    一文解決pom.xml報錯Dependency "xxx" not f

    我們在使用maven進(jìn)行jar包管理時有時會遇到pom.xml中報錯Dependency “XXX” not found,所以在本文中將給大家介紹一下pom.xml報錯Dependency "xxx" not found的解決方案,需要的朋友可以參考下
    2024-01-01
  • Java8新特性O(shè)ptional類及新時間日期API示例詳解

    Java8新特性O(shè)ptional類及新時間日期API示例詳解

    這篇文章主要為大家介紹了Java8新特性O(shè)ptional類及新時間日期API示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • Springboot實現(xiàn)導(dǎo)入導(dǎo)出Excel的方法

    Springboot實現(xiàn)導(dǎo)入導(dǎo)出Excel的方法

    今天帶各位小伙伴學(xué)習(xí)Springboot實現(xiàn)導(dǎo)入導(dǎo)出Excel的方法,文中有非常詳細(xì)的介紹,對正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下
    2021-05-05
  • 詳解Java中AC自動機的原理與實現(xiàn)

    詳解Java中AC自動機的原理與實現(xiàn)

    AC自動機是一個多模式匹配算法,在模式匹配領(lǐng)域被廣泛應(yīng)用。本文將詳細(xì)為大家介紹AC自動機的原理與實現(xiàn)方法,感興趣的可以了解一下
    2022-05-05
  • Spring 定時任務(wù)@Scheduled 注解四大參數(shù)用法解析

    Spring 定時任務(wù)@Scheduled 注解四大參數(shù)用法解析

    本文詳細(xì)介紹了Spring框架中使用@Scheduled注解實現(xiàn)定時任務(wù)的方法,重點講解了fixedRate、fixedDelay、cron和initialDelay這四個參數(shù)的用法,并通過實例代碼進(jìn)行了詳細(xì)說明,感興趣的朋友一起看看吧
    2025-01-01
  • Java?Stream實現(xiàn)多字段分組groupingBy操作詳解

    Java?Stream實現(xiàn)多字段分組groupingBy操作詳解

    Stream是Java8的一個新特性,主要用戶集合數(shù)據(jù)的處理,如排序、過濾、去重等等功能,本文就來講講如何利用Stream實現(xiàn)比較優(yōu)雅的按多字段進(jìn)行分組groupingBy吧
    2023-06-06
  • SpringBoot分布式文件存儲數(shù)據(jù)庫mongod

    SpringBoot分布式文件存儲數(shù)據(jù)庫mongod

    MongoDB是一個基于分布式文件存儲的NoSQL數(shù)據(jù)庫,由C++語言編寫,旨在為Web應(yīng)用提供可擴展的高性能數(shù)據(jù)存儲解決方案。MongoDB是一個介于關(guān)系數(shù)據(jù)庫和非關(guān)系數(shù)據(jù)庫之間的產(chǎn)品,是非關(guān)系數(shù)據(jù)庫中功能最豐富最像關(guān)系數(shù)據(jù)庫的
    2023-02-02
  • 利用java反射機制實現(xiàn)自動調(diào)用類的簡單方法

    利用java反射機制實現(xiàn)自動調(diào)用類的簡單方法

    下面小編就為大家?guī)硪黄胘ava反射機制實現(xiàn)自動調(diào)用類的簡單方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-08-08
  • 啟動異常invalid constant type:15的解決方案

    啟動異常invalid constant type:15的解決方案

    今天小編就為大家分享一篇關(guān)于啟動異常invalid constant type:15的解決方案,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12

最新評論