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

Java中序列化和反序列化的完整講解

 更新時(shí)間:2022年11月11日 16:00:33   作者:九塊六  
序列化是將對象轉(zhuǎn)換成二進(jìn)制字節(jié)流的過程;反序列化是從二進(jìn)制字節(jié)流中恢復(fù)對象的過程。文中將為大家詳細(xì)講講二者的原理與實(shí)現(xiàn),需要的可以參考一下

一、序列化

1.1.Serialization(序列化):

將java對象以一連串的字節(jié)保存在磁盤文件中的過程,也可以說是保存java對象狀態(tài)的過程。序列化可以將數(shù)據(jù)永久保存在磁盤上(通常保存在文件中)

1.2.deserialization(反序列化)

將保存在磁盤文件中的java字節(jié)碼重新轉(zhuǎn)換成java對象稱為反序列化

二、序列化和反序列化的應(yīng)用

兩個(gè)進(jìn)程在遠(yuǎn)程通信時(shí),可以發(fā)送多種數(shù)據(jù),包括文本、圖片、音頻、視頻等,這些數(shù)據(jù)都是以二進(jìn)制序列的形式在網(wǎng)絡(luò)上傳輸。

java是面向?qū)ο蟮拈_發(fā)方式,一切都是java對象,想要在網(wǎng)絡(luò)中傳輸java對象,可以使用序列化和反序列化去實(shí)現(xiàn),發(fā)送發(fā)需要將java對象轉(zhuǎn)換為字節(jié)序列,然后在網(wǎng)絡(luò)上傳送,接收方收到字符序列后,會(huì)通過反序列化將字節(jié)序列恢復(fù)成java對象。

java序列化的優(yōu)點(diǎn):

  • 實(shí)現(xiàn)了數(shù)據(jù)的持久化,通過序列化可以把數(shù)據(jù)持久地保存在硬盤上(磁盤文件)。
  • 利用序列化實(shí)現(xiàn)遠(yuǎn)程通信,在網(wǎng)絡(luò)上傳輸字節(jié)序列

三、序列化和反序列化地實(shí)現(xiàn)

3.1.JDK類庫提供的序列化API

java.io.ObjectOutputStream    

表示對象輸出流,其中writeObject(Object obj)方法可以將給定參數(shù)的obj對象進(jìn)行序列化,將轉(zhuǎn)換的一連串的字節(jié)序列寫到指定的目標(biāo)輸出流中。

java.io.ObjectInputStream

該類表示對象輸入流,該類下的readObject(Object obj)方法會(huì)從源輸入流中讀取字節(jié)序列,并將它反序列化為一個(gè)java對象并返回

3.2.序列化要求

實(shí)現(xiàn)序列化的類對象必須實(shí)現(xiàn)了Serializable類或Externalizable類才能被序列化,否則會(huì)拋出異常

3.3.實(shí)現(xiàn)java序列化和反序列化的三種方法

現(xiàn)在要對student類進(jìn)行序列化和反序列化,遵循以下方法:

3.3.1.方法一

若student類實(shí)現(xiàn)了serializable接口,則可以通過objectOutputstream和objectinputstream默認(rèn)的序列化和反序列化方式,對非transient的實(shí)例變量進(jìn)行序列化和反序列化

3.3.2. 方法二

若student類實(shí)現(xiàn)了serializable接口,并且定義了writeObject(objectOutputStream out)和

readObject(objectinputStream in)方法,則可以直接調(diào)用student類的兩種方法進(jìn)行序列化和反序列化

3.3.3.方法三

若student類實(shí)現(xiàn)了Externalizable接口,則必須實(shí)現(xiàn)readExternal(Objectinput in)和writeExternal(Objectoutput out)方法進(jìn)行序列化和反序列化 

3.4.序列化步驟 

public static void main(String[] args) {
    File filename = new File("E:/Student1.txt");
    try {
            // 第一步,創(chuàng)建一個(gè)輸出流對象,它可以包裝一個(gè)輸出流對象,如:文件輸出流
            FileOutputStream fileOutputStream = new FileOutputStream(filename);
            ObjectOutputStream out = new ObjectOutputStream(fileOutputStream);
            // 第二步,通過輸出流對象的 writeObject()方法寫對象,從 java 輸出到本地文件 out
            out.writeObject("第一次輸出:第一次打卡哦");
            out.writeObject("第二次輸出:第二次打卡");
    } catch (IOException e) {
            e.printStackTrace();
    }
}

3.5.反序列化操作

public static void main(String[] args) {
    File filename = new File("E:/Student1.txt");
    try {
            // 第一步:創(chuàng)建文件輸入流對象
            FileInputStream fileInputStream = new FileInputStream(filename);
            ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);
            // 調(diào)用readObject()方法,本地文件讀取數(shù)據(jù),輸入到程序當(dāng)中
            System.out.println(inputStream.readObject());
            System.out.println(inputStream.readObject());
    } catch (IOException e) {
            e.printStackTrace();
    } catch (ClassNotFoundException e) {
            e.printStackTrace();
    }
}

為了保證正確讀取數(shù)據(jù),對象輸出流寫入對象的順序與對象輸入流讀取對象的順序一致

四、CustomerForm 類序列化和反序列化演示

4.1.先創(chuàng)建一個(gè)實(shí)現(xiàn)了serializable接口的CustomerForm 類

Serializable (/?s??ri??la?z?bl/) 序列化

import lombok.Data;
import java.io.Serializable;
import java.util.List;
 
/**
 * <p>Java class for attachmentForm complex type.
 * 
 */
@Data
public class CustomerForm implements Serializable {
    protected String requestCode;
    protected List<Customer> reqData;
    /**
     * transient 修飾的屬性不能序列化 * 
     */
    private transient String msg;
    private static String name = "被static修飾的name";
}

把CustomerForm類的對象序列化到CustomerForm.txt 文件(E:/CustomerForm.txt)中,并對文件進(jìn)行反序列化獲取數(shù)據(jù):

public static void main(String[] args) {
    FileOutputStream fileOutputStream = null;
    ObjectOutputStream out = null;
    FileInputStream fileInputStream = null;
    ObjectInputStream inputStream = null;       
    try {            
        File file = new File("E:/CustomerForm.txt");            
        if (file.exists()){                
            System.out.println("文件已存在");            
        } else {          
            file.createNewFile();            
        }            
        CustomerForm customerForm = new CustomerForm();           
        customerForm.setRequestCode("1-2-3-4-5-6-7-8-9");            
        // 序列化 第一步,創(chuàng)建一個(gè)輸出流對象,它可以包裝一個(gè)輸出流對象,如:文件輸出流            
        fileOutputStream = new FileOutputStream(file);            
        out = new ObjectOutputStream(fileOutputStream);            
        // 序列化 第二步,通過輸出流對象的 writeObject()方法寫對象,從 java 輸出到本地文件 out            
        out.writeObject(customerForm);            
        // 反序列化 第一步:創(chuàng)建文件輸入流對象            
        fileInputStream = new FileInputStream(file);            
        inputStream = new ObjectInputStream(fileInputStream);           
        // 反序列化 第二步:調(diào)用readObject()方法,本地文件讀取數(shù)據(jù),輸入到程序當(dāng)中            
        System.out.println(inputStream.readObject());        
    } catch (IOException e) {            
        e.printStackTrace();       
    } catch (ClassNotFoundException e) {            
        e.printStackTrace();       
    } finally {
        out.close();
        fileOutputStream.close();
        fileInputStream.close();
        inputStream.close();
    }
}

序列化之后本地文件訪問結(jié)果:

反序列化結(jié)果:

4.2.transient 關(guān)鍵字

transient ( /?træn?(?)nt/)瞬變的

transient 修飾的屬性不能參加序列化

以上程序重新執(zhí)行:

public static void main(String[] args) {       
    try {            
        File file = new File("E:/CustomerForm.txt");            
        if (file.exists()){                
            System.out.println("文件已存在");            
        } else {          
            file.createNewFile();            
        }            
        CustomerForm customerForm = new CustomerForm();           
        customerForm.setRequestCode("1-2-3-4-5-6-7-8-9");   
        /**
         * transient 修飾的屬性不能序列化 *
         */
        customerForm.setMsg("此屬性不能參加序列化");         
        // 序列化 第一步,創(chuàng)建一個(gè)輸出流對象,它可以包裝一個(gè)輸出流對象,如:文件輸出流            
        FileOutputStream fileOutputStream = new FileOutputStream(file);            
        ObjectOutputStream out = new ObjectOutputStream(fileOutputStream);            
        // 序列化 第二步,通過輸出流對象的 writeObject()方法寫對象,從 java 輸出到本地文件 out            
        out.writeObject(customerForm);            
        // 反序列化 第一步:創(chuàng)建文件輸入流對象            
        FileInputStream fileInputStream = new FileInputStream(file);            
        ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);           
        // 反序列化 第二步:調(diào)用readObject()方法,本地文件讀取數(shù)據(jù),輸入到程序當(dāng)中            
        System.out.println(inputStream.readObject());        
    } catch (IOException e) {            
        e.printStackTrace();       
    } catch (ClassNotFoundException e) {            
        e.printStackTrace();       
    }
}

執(zhí)行結(jié)果:

從結(jié)果看出 被transient關(guān)鍵字修飾的變量 msg 賦值內(nèi)容沒有被序列化,被修改為null,被static修飾的屬性不能被實(shí)例化

五、Externalizable接口實(shí)現(xiàn)序列化與反序列化

Externalizable 可外部化的

Externalizable接口繼承Serializable接口,實(shí)現(xiàn)Externalizable接口需要實(shí)現(xiàn)readExternal()方法和writeExternal()方法,這兩個(gè)方法是抽象方法,對應(yīng)的是serializable接口的readObject()方法和writeObject()方法,可以理解為把serializable的兩個(gè)方法抽象出來。Externalizable沒有serializable的限制,static和transient關(guān)鍵字修飾的屬性也能進(jìn)行序列化。

5.1.Externalizable 的不同點(diǎn)

Externalizable沒有serializable的限制,transient關(guān)鍵字修飾的屬性也能進(jìn)行序列化

5.2.CustomerForm 實(shí)現(xiàn)類 Externalizable

import lombok.Data;
import java.io.Serializable;
import java.util.List;
 
/**
 * <p>Java class for attachmentForm complex type.
 * 
 */
@Data
public class CustomerForm implements Externalizable{
    protected String requestCode;
    protected List<Customer> reqData;
    private transient String msg;
    private static String name = "被static修飾的name";
 
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(requestCode);
        out.writeObject(msg);
        out.writeObject(reqData);
    }
 
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        requestCode = (String) in.readObject();
        msg = (String) in.readObject();
        reqData = (List<Customer>) in.readObject();
    }
}

實(shí)現(xiàn) Externalizable 類 后需要重寫 writeExternal()、readExternal() 方法

5.3.Externalizable 實(shí)現(xiàn)序列化和反序列化

public static void main(String[] args) {       
    try {            
        File file = new File("E:/CustomerForm.txt");            
        if (file.exists()){                
            System.out.println("文件已存在");            
        } else {          
            file.createNewFile();            
        }            
        CustomerForm customerForm = new CustomerForm();           
        customerForm.setRequestCode("1-2-3-4-5-6-7-8-9");   
        customerForm.setMsg("該屬性被transient修飾");         
        // 序列化 第一步,創(chuàng)建一個(gè)輸出流對象,它可以包裝一個(gè)輸出流對象,如:文件輸出流            
        FileOutputStream fileOutputStream = new FileOutputStream(file);            
        ObjectOutputStream out = new ObjectOutputStream(fileOutputStream);            
        // 序列化 第二步,通過輸出流對象的 writeObject()方法寫對象,從 java 輸出到本地文件 out            
        out.writeObject(customerForm);            
        // 反序列化 第一步:創(chuàng)建文件輸入流對象            
        FileInputStream fileInputStream = new FileInputStream(file);            
        ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);           
        // 反序列化 第二步:調(diào)用readObject()方法,本地文件讀取數(shù)據(jù),輸入到程序當(dāng)中            
        System.out.println(inputStream.readObject());        
    } catch (IOException e) {            
        e.printStackTrace();       
    } catch (ClassNotFoundException e) {            
        e.printStackTrace();       
    }
}

執(zhí)行結(jié)果:

可以看到被transient關(guān)鍵字修飾的變量msg已經(jīng)參與了實(shí)例化,被static修飾的變量不能被實(shí)例化

總結(jié)

序列化和反序列化可以過這兩種方式來實(shí)現(xiàn):

1、Bean對象可以通過Serializable接口實(shí)現(xiàn)序列化與反序列化

2、Bean對象可以通過Externalizable接口實(shí)現(xiàn)序列化與反序列化

不同點(diǎn)

1、Externalizable接口實(shí)現(xiàn)實(shí)例化,需要重寫 writeExternal()、readExternal() 方法

2、Externalizable接口實(shí)現(xiàn)實(shí)例化,不受 transient關(guān)鍵字限制

3、Serializable接口實(shí)現(xiàn),transient關(guān)鍵字修飾后,不能參與實(shí)例化

4、被static修飾的變量(都)不能被實(shí)例化

原因:被static修飾的屬性是所有類共享的,如果可以序列化,就會(huì)出現(xiàn)下面的情況,當(dāng)我們序列化某個(gè)類的一個(gè)對象到某個(gè)文件后,這個(gè)文件中的對象的那個(gè)被static修飾的屬性值會(huì)固定下來,當(dāng)另外一個(gè)普通的的對象修改了該static屬性后,我們再去反序列化那個(gè)文件中的對象,就會(huì)得到和后面的對象不同的static屬性值,這顯然違背了static關(guān)鍵字誕生的初衷

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

相關(guān)文章

  • SpringMVC攔截器失效問題及解決方法

    SpringMVC攔截器失效問題及解決方法

    這篇文章主要介紹了SpringMVC?攔截器和異常處理器,以及SpringMVC攔截器失效分析解決方案,文中補(bǔ)充介紹了SpringMVC?攔截器和異常處理器的相關(guān)知識(shí),需要的朋友可以參考下
    2024-01-01
  • mybatis(mybatis-plus)映射文件(XML文件)中特殊字符轉(zhuǎn)義的實(shí)現(xiàn)

    mybatis(mybatis-plus)映射文件(XML文件)中特殊字符轉(zhuǎn)義的實(shí)現(xiàn)

    XML 文件在解析時(shí)會(huì)將五種特殊字符進(jìn)行轉(zhuǎn)義,本文主要介紹了mybatis(mybatis-plus)映射文件(XML文件)中特殊字符轉(zhuǎn)義的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • spring boot在啟動(dòng)項(xiàng)目之后執(zhí)行的實(shí)現(xiàn)方法

    spring boot在啟動(dòng)項(xiàng)目之后執(zhí)行的實(shí)現(xiàn)方法

    在開發(fā)時(shí)有時(shí)候需要在整個(gè)應(yīng)用開始運(yùn)行時(shí)執(zhí)行一些特定代碼,比如初始化環(huán)境,下面這篇文章就來給大家介紹了關(guān)于spring boot在啟動(dòng)項(xiàng)目之后執(zhí)行自己要執(zhí)行的東西的實(shí)現(xiàn)方法,文中給出了詳細(xì)的示例代碼,需要的朋友可以參考下。
    2017-09-09
  • java如何獲取10位和13位時(shí)間戳

    java如何獲取10位和13位時(shí)間戳

    這篇文章主要介紹了java如何獲取10位和13位時(shí)間戳問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • 使用SpringBoot整合Activiti6工作流的操作方法

    使用SpringBoot整合Activiti6工作流的操作方法

    這篇文章主要介紹了使用SpringBoot整合Activiti6工作流,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • 如何在 Java 中利用 redis 實(shí)現(xiàn) LBS 服務(wù)

    如何在 Java 中利用 redis 實(shí)現(xiàn) LBS 服務(wù)

    基于位置的服務(wù),是指通過電信移動(dòng)運(yùn)營商的無線電通訊網(wǎng)絡(luò)或外部定位方式,獲取移動(dòng)終端用戶的位置信息,在GIS平臺(tái)的支持下,為用戶提供相應(yīng)服務(wù)的一種增值業(yè)務(wù)。下面我們來一起學(xué)習(xí)一下吧
    2019-06-06
  • SpringBoot中打印SQL語句的幾種方法實(shí)現(xiàn)

    SpringBoot中打印SQL語句的幾種方法實(shí)現(xiàn)

    本文主要介紹了SpringBoot中打印SQL語句的幾種方法實(shí)現(xiàn),,通過打印SQL語句可以幫助開發(fā)人員快速了解數(shù)據(jù)庫的操作情況,進(jìn)而進(jìn)行性能分析和調(diào)試,感興趣的可以了解一下
    2023-11-11
  • Mybatis超級(jí)強(qiáng)大的動(dòng)態(tài)SQL語句大全

    Mybatis超級(jí)強(qiáng)大的動(dòng)態(tài)SQL語句大全

    MyBatis的動(dòng)態(tài)SQL是基于OGNL表達(dá)式的,它可以幫助我們方便的在SQL語句中實(shí)現(xiàn)某些邏輯,下面這篇文章主要給大家介紹了關(guān)于Mybatis超級(jí)強(qiáng)大的動(dòng)態(tài)SQL語句的相關(guān)資料,需要的朋友可以參考下
    2022-05-05
  • Java中Comparable和Comparator兩種比較器的區(qū)別詳解

    Java中Comparable和Comparator兩種比較器的區(qū)別詳解

    這篇文章主要介紹了Java中Comparable和Comparator兩種比較器的區(qū)別詳解,Comparable接口將比較代碼嵌入自身類中,像Integer、String等這些基本類型的JAVA封裝類都已經(jīng)實(shí)現(xiàn)了Comparable接口,這些類對象本身就支持和自己比較,需要的朋友可以參考下
    2023-09-09
  • 一文深入分析java.lang.ClassNotFoundException異常

    一文深入分析java.lang.ClassNotFoundException異常

    這篇文章主要給大家介紹了關(guān)于java.lang.ClassNotFoundException異常的相關(guān)資料,java.lang.ClassNotFoundException是Java編程時(shí)經(jīng)常會(huì)遇到的一個(gè)異常,它表示JVM在嘗試加載某個(gè)類時(shí)未能找到該類,需要的朋友可以參考下
    2023-10-10

最新評(píng)論

黎川县| 修水县| 克拉玛依市| 临武县| 永吉县| 宣城市| 西平县| 德格县| 治多县| 青铜峡市| 稷山县| 调兵山市| 长乐市| 汨罗市| 永善县| 西宁市| 瑞昌市| 衡阳市| 循化| 辽宁省| 聊城市| 诸暨市| 乌拉特中旗| 新平| 吉木乃县| 酉阳| 两当县| 德庆县| 多伦县| 青神县| 磐安县| 南投县| 桑日县| 泰和县| 星座| 奎屯市| 报价| 新乡县| 玉门市| 巴彦县| 吉首市|