欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

一、序列化

1.1.Serialization(序列化):

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

1.2.deserialization(反序列化)

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

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

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

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

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

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

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

3.1.JDK類(lèi)庫(kù)提供的序列化API

java.io.ObjectOutputStream    

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

java.io.ObjectInputStream

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

3.2.序列化要求

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

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

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

3.3.1.方法一

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

3.3.2. 方法二

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

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

3.3.3.方法三

若student類(lèi)實(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è)輸出流對(duì)象,它可以包裝一個(gè)輸出流對(duì)象,如:文件輸出流
            FileOutputStream fileOutputStream = new FileOutputStream(filename);
            ObjectOutputStream out = new ObjectOutputStream(fileOutputStream);
            // 第二步,通過(guò)輸出流對(duì)象的 writeObject()方法寫(xiě)對(duì)象,從 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)建文件輸入流對(duì)象
            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ù),對(duì)象輸出流寫(xiě)入對(duì)象的順序與對(duì)象輸入流讀取對(duì)象的順序一致

四、CustomerForm 類(lèi)序列化和反序列化演示

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

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類(lèi)的對(duì)象序列化到CustomerForm.txt 文件(E:/CustomerForm.txt)中,并對(duì)文件進(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è)輸出流對(duì)象,它可以包裝一個(gè)輸出流對(duì)象,如:文件輸出流            
        fileOutputStream = new FileOutputStream(file);            
        out = new ObjectOutputStream(fileOutputStream);            
        // 序列化 第二步,通過(guò)輸出流對(duì)象的 writeObject()方法寫(xiě)對(duì)象,從 java 輸出到本地文件 out            
        out.writeObject(customerForm);            
        // 反序列化 第一步:創(chuàng)建文件輸入流對(duì)象            
        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();
    }
}

序列化之后本地文件訪問(wèn)結(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è)輸出流對(duì)象,它可以包裝一個(gè)輸出流對(duì)象,如:文件輸出流            
        FileOutputStream fileOutputStream = new FileOutputStream(file);            
        ObjectOutputStream out = new ObjectOutputStream(fileOutputStream);            
        // 序列化 第二步,通過(guò)輸出流對(duì)象的 writeObject()方法寫(xiě)對(duì)象,從 java 輸出到本地文件 out            
        out.writeObject(customerForm);            
        // 反序列化 第一步:創(chuàng)建文件輸入流對(duì)象            
        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)容沒(méi)有被序列化,被修改為null,被static修飾的屬性不能被實(shí)例化

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

Externalizable 可外部化的

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

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

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

5.2.CustomerForm 實(shí)現(xiàn)類(lèi) 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 類(lèi) 后需要重寫(xiě) 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è)輸出流對(duì)象,它可以包裝一個(gè)輸出流對(duì)象,如:文件輸出流            
        FileOutputStream fileOutputStream = new FileOutputStream(file);            
        ObjectOutputStream out = new ObjectOutputStream(fileOutputStream);            
        // 序列化 第二步,通過(guò)輸出流對(duì)象的 writeObject()方法寫(xiě)對(duì)象,從 java 輸出到本地文件 out            
        out.writeObject(customerForm);            
        // 反序列化 第一步:創(chuàng)建文件輸入流對(duì)象            
        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é)

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

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

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

不同點(diǎn)

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

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

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

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

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

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

相關(guān)文章

  • 利用java實(shí)現(xiàn)二叉搜索樹(shù)

    利用java實(shí)現(xiàn)二叉搜索樹(shù)

    這篇文章主要介紹了利用java實(shí)現(xiàn)二叉搜索樹(shù),文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • java.util.Collections類(lèi)—emptyList()方法的使用

    java.util.Collections類(lèi)—emptyList()方法的使用

    這篇文章主要介紹了java.util.Collections類(lèi)—emptyList()方法的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • java讀取XML文件的四種方法總結(jié)(必看篇)

    java讀取XML文件的四種方法總結(jié)(必看篇)

    下面小編就為大家?guī)?lái)一篇java讀取XML文件的四種方法總結(jié)(必看篇)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • 微服務(wù)實(shí)戰(zhàn)之怎樣提升springboot服務(wù)吞吐量

    微服務(wù)實(shí)戰(zhàn)之怎樣提升springboot服務(wù)吞吐量

    這篇文章主要介紹了微服務(wù)實(shí)戰(zhàn)之怎樣提升springboot服務(wù)吞吐量方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • SpringBoot Redis安裝過(guò)程詳解

    SpringBoot Redis安裝過(guò)程詳解

    這篇文章主要介紹了SpringBoot Redis安裝過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • java使用枚舉封裝錯(cuò)誤碼及錯(cuò)誤信息詳解

    java使用枚舉封裝錯(cuò)誤碼及錯(cuò)誤信息詳解

    這篇文章主要介紹了java使用枚舉封裝錯(cuò)誤碼及錯(cuò)誤信息,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java OpenCV實(shí)現(xiàn)圖像鏡像翻轉(zhuǎn)效果

    Java OpenCV實(shí)現(xiàn)圖像鏡像翻轉(zhuǎn)效果

    這篇文章主要為大家詳細(xì)介紹了Java OpenCV實(shí)現(xiàn)圖像鏡像翻轉(zhuǎn)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • postgresql 實(shí)現(xiàn)16進(jìn)制字符串轉(zhuǎn)10進(jìn)制數(shù)字

    postgresql 實(shí)現(xiàn)16進(jìn)制字符串轉(zhuǎn)10進(jìn)制數(shù)字

    這篇文章主要介紹了postgresql 實(shí)現(xiàn)16進(jìn)制字符串轉(zhuǎn)10進(jìn)制數(shù)字操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • 支持生產(chǎn)阻塞的Java線程池

    支持生產(chǎn)阻塞的Java線程池

    在各種并發(fā)編程模型中,生產(chǎn)者-消費(fèi)者模式大概是最常用的了。在實(shí)際工作中,對(duì)于生產(chǎn)消費(fèi)的速度,通常需要做一下權(quán)衡
    2014-04-04
  • 詳解SpringBoot自定義配置與整合Druid

    詳解SpringBoot自定義配置與整合Druid

    Druid是alibaba開(kāi)源平臺(tái)上一個(gè)數(shù)據(jù)庫(kù)連接池實(shí)現(xiàn),結(jié)合了C3P0,DBCP等DB池的優(yōu)點(diǎn),同時(shí)也有Web監(jiān)控界面。這篇文章主要介紹了Java之SpringBoot自定義配置與整合Druid的相關(guān)知識(shí),需要的朋友可以參考下
    2021-09-09

最新評(píng)論