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

Java 對(duì)象序列化 NIO NIO2詳細(xì)介紹及解析

 更新時(shí)間:2017年02月13日 08:44:36   投稿:lqh  
這篇文章主要介紹了Java 對(duì)象序列化 NIO NIO2詳細(xì)介紹及解析的相關(guān)資料,序列化機(jī)制可以使對(duì)象可以脫離程序的運(yùn)行而對(duì)立存在,需要的朋友可以參考下

Java 對(duì)象序列化 NIO NIO2詳細(xì)介紹及解析

概要:

對(duì)象序列化

對(duì)象序列化機(jī)制允許把內(nèi)存中的Java對(duì)象轉(zhuǎn)換成與平臺(tái)無(wú)關(guān)的二進(jìn)制流,從而可以保存到磁盤(pán)或者進(jìn)行網(wǎng)絡(luò)傳輸,其它程序獲得這個(gè)二進(jìn)制流后可以將其恢復(fù)成原來(lái)的Java對(duì)象。 序列化機(jī)制可以使對(duì)象可以脫離程序的運(yùn)行而對(duì)立存在

序列化的含義和意義

序列化

序列化機(jī)制可以使對(duì)象可以脫離程序的運(yùn)行而對(duì)立存在

序列化(Serialize)指將一個(gè)java對(duì)象寫(xiě)入IO流中,與此對(duì)應(yīng)的是,對(duì)象的反序列化(Deserialize)則指從IO流中恢復(fù)該java對(duì)象

如果需要讓某個(gè)對(duì)象可以支持序列化機(jī)制,必須讓它的類(lèi)是可序列化(serializable),為了讓某個(gè)類(lèi)可序列化的,必須實(shí)現(xiàn)如下兩個(gè)接口之一:

  • Serializable:標(biāo)記接口,實(shí)現(xiàn)該接口無(wú)須實(shí)現(xiàn)任何方法,只是表明該類(lèi)的實(shí)例是可序列化的
  • Externalizable

所有在網(wǎng)絡(luò)上傳輸?shù)膶?duì)象都應(yīng)該是可序列化的,否則將會(huì)出現(xiàn)異常;所有需要保存到磁盤(pán)里的對(duì)象的類(lèi)都必須可序列化;程序創(chuàng)建的每個(gè)JavaBean類(lèi)都實(shí)現(xiàn)Serializable;

使用對(duì)象流實(shí)現(xiàn)序列化

實(shí)現(xiàn)Serializable實(shí)現(xiàn)序列化的類(lèi),程序可以通過(guò)如下兩個(gè)步驟來(lái)序列化該對(duì)象:

1.創(chuàng)建一個(gè)ObjectOutputStream,這個(gè)輸出流是一個(gè)處理流,所以必須建立在其他節(jié)點(diǎn)流的基礎(chǔ)之上

// 創(chuàng)建個(gè)ObjectOutputStream輸出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt"));

2.調(diào)用ObjectOutputStream對(duì)象的writeObject方法輸出可序列化對(duì)象

// 將一個(gè)Person對(duì)象輸出到輸出流中
oos.writeObject(per);

定義一個(gè)NbaPlayer類(lèi),實(shí)現(xiàn)Serializable接口,該接口標(biāo)識(shí)該類(lèi)的對(duì)象是可序列化的

public class NbaPlayer implements java.io.Serializable
{
  private String name;
  private int number;
  // 注意此處沒(méi)有提供無(wú)參數(shù)的構(gòu)造器!
  public NbaPlayer(String name, int number)
  {
    System.out.println("有參數(shù)的構(gòu)造器");
    this.name = name;
    this.number = number;
  }

  // name的setter和getter方法
  public void setName(String name)
  {
    this.name = name;
  }
  public String getName()
  {
    return this.name;
  }

  // number的setter和getter方法
  public void setNumber(int number)
  {
    this.number = number;
  }
  public int getNumber()
  {
    return this.number;
  }
}

使用ObjectOutputStream將一個(gè)NbaPlayer對(duì)象寫(xiě)入磁盤(pán)文件

import java.io.*;

public class WriteObject
{
  public static void main(String[] args)
  {
    try(
      // 創(chuàng)建一個(gè)ObjectOutputStream輸出流
      ObjectOutputStream oos = new ObjectOutputStream(
        new FileOutputStream("object.txt")))
    {
      NbaPlayer player = new NbaPlayer("維斯布魯克", 0);
      // 將player對(duì)象寫(xiě)入輸出流
      oos.writeObject(player);
    }
    catch (IOException ex)
    {
      ex.printStackTrace();
    }
  }
}

反序列化

從二進(jìn)制流中恢復(fù)Java對(duì)象,則需要使用反序列化,程序可以通過(guò)如下兩個(gè)步驟來(lái)序列化該對(duì)象:

1.創(chuàng)建一個(gè)ObjectInputStream輸入流,這個(gè)輸入流是一個(gè)處理流,所以必須建立在其他節(jié)點(diǎn)流的基礎(chǔ)之上

// 創(chuàng)建個(gè)ObjectInputStream輸出流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.txt"));

2.調(diào)用ObjectInputStream對(duì)象的readObject()方法讀取流中的對(duì)象,該方法返回一個(gè)Object類(lèi)型的Java對(duì)象,可進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換成其真實(shí)的類(lèi)型

// 從輸入流中讀取一個(gè)Java對(duì)象,并將其強(qiáng)制類(lèi)型轉(zhuǎn)換為Person類(lèi)
Person p = (Person)ois.readObject();

從object.txt文件中讀取NbaPlayer對(duì)象的步驟

import java.io.*;
public class ReadObject
{
  public static void main(String[] args)
  {
    try(
      // 創(chuàng)建一個(gè)ObjectInputStream輸入流
      ObjectInputStream ois = new ObjectInputStream(
        new FileInputStream("object.txt")))
    {
      // 從輸入流中讀取一個(gè)Java對(duì)象,并將其強(qiáng)制類(lèi)型轉(zhuǎn)換為NbaPlayer類(lèi)
      NbaPlayer player = (NbaPlayer)ois.readObject();
      System.out.println("名字為:" + player.getName()
        + "\n號(hào)碼為:" + player.getNumber());
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
  }
}

反序列化讀取的僅僅是Java對(duì)象的數(shù)據(jù),而不是Java類(lèi),因此采用反序列化恢復(fù)Java對(duì)象時(shí),必須提供Java對(duì)象所屬的class文件,否則會(huì)引發(fā)ClassNotFoundException異常;反序列化機(jī)制無(wú)須通過(guò)構(gòu)造器來(lái)初始化Java對(duì)象

如果使用序列化機(jī)制向文件中寫(xiě)入了多個(gè)Java對(duì)象,使用反序列化機(jī)制恢復(fù)對(duì)象必須按照實(shí)際寫(xiě)入的順序讀取。當(dāng)一個(gè)可序列化類(lèi)有多個(gè)父類(lèi)時(shí)(包括直接父類(lèi)和間接父類(lèi)),這些父類(lèi)要么有無(wú)參的構(gòu)造器,要么也是可序列化的—否則反序列化將拋出InvalidClassException異常。如果父類(lèi)是不可序列化的,只是帶有無(wú)參數(shù)的構(gòu)造器,則該父類(lèi)定義的Field值不會(huì)被序列化到二進(jìn)制流中

對(duì)象引用的序列化

如果某個(gè)類(lèi)的Field類(lèi)型不是基本類(lèi)型或者String類(lèi)型,而是另一個(gè)引用類(lèi)型,那么這個(gè)引用類(lèi)型必須是可序列化的,否則有用該類(lèi)型的Field的類(lèi)也是不可序列化的

public class AllStar implements java.io.Serializable
{
  private String name;
  private NbaPlayer player;
  public AllStar(String name, NbaPlayer player)
  {
    this.name = name;
    this.player = player;
  }
  // 此處省略了name和player的setter和getter方法

  // name的setter和getter方法
  public String getName()
  {
    return this.name;
  }

  public void setName(String name)
  {
    this.name = name;
  }

  // player的setter和getter方法
  public NbaPlayer getPlayer() 
  {
    return player;
  }

  public void setPlayer(NbaPlayer player) 
  {
    this.player = player;
  }
}

Java特殊的序列化算法

  • 所有保存到磁盤(pán)中的對(duì)象都有一個(gè)序列化編號(hào)
  • 當(dāng)程序試圖序列化一個(gè)對(duì)象時(shí),程序?qū)⑾葯z查該對(duì)象是否已經(jīng)被序列化過(guò),只有該對(duì)象從未(在本次虛擬中機(jī))被序列化過(guò),系統(tǒng)才會(huì)將該對(duì)象轉(zhuǎn)換成字節(jié)序列并輸出
  • 如果某個(gè)對(duì)象已經(jīng)序列化過(guò),程序?qū)⒅皇侵苯虞敵鲆粋€(gè)序列化編號(hào),而不是再次重新序列化該對(duì)象
import java.io.*;
public class WriteAllStar
{
  public static void main(String[] args)
  {
    try(
      // 創(chuàng)建一個(gè)ObjectOutputStream輸出流
      ObjectOutputStream oos = new ObjectOutputStream(
        new FileOutputStream("allStar.txt")))
    {
      NbaPlayer player = new NbaPlayer("詹姆斯哈登", 13);
      AllStar allStar1 = new AllStar("西部全明星", player);
      AllStar allStar2 = new AllStar("首發(fā)后衛(wèi)", player);
      // 依次將四個(gè)對(duì)象寫(xiě)入輸出流
      oos.writeObject(allStar1);
      oos.writeObject(allStar2);
      oos.writeObject(player);
      oos.writeObject(allStar2);
    }
    catch (IOException ex)
    {
      ex.printStackTrace();
    }
  }
}

4個(gè)寫(xiě)入輸出流的對(duì)象,實(shí)際上只序列化了3個(gè),而且序列的兩個(gè)AllStar對(duì)象的player引用實(shí)際是同一個(gè)NbaPlayer對(duì)象。以下程序讀取序列化文件中的對(duì)象

import java.io.*;
public class ReadAllStar
{
  public static void main(String[] args)
  {
    try(
      // 創(chuàng)建一個(gè)ObjectInputStream輸出流
      ObjectInputStream ois = new ObjectInputStream(
        new FileInputStream("allStar.txt")))
    {
      // 依次讀取ObjectInputStream輸入流中的四個(gè)對(duì)象
      AllStar star1 = (AllStar)ois.readObject();
      AllStar star2 = (AllStar)ois.readObject();
      NbaPlayer player = (NbaPlayer)ois.readObject();
      AllStar star3 = (AllStar)ois.readObject();
      // 輸出true
      System.out.println("star1的player引用和player是否相同:"
        + (star1.getPlayer() == player));
      // 輸出true
      System.out.println("star2的player引用和player是否相同:"
        + (star2.getPlayer() == player));
      // 輸出true
      System.out.println("star2和star3是否是同一個(gè)對(duì)象:"
        + (star2 == star3));
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
  }
}

如果多次序列化同一個(gè)可變Java對(duì)象時(shí),只有第一次序列化時(shí)才會(huì)把該Java對(duì)象轉(zhuǎn)換成字節(jié)序列并輸出

當(dāng)使用Java序列化機(jī)制序列化可變對(duì)象時(shí),只有第一次調(diào)用WriteObject()方法來(lái)輸出對(duì)象時(shí)才會(huì)將對(duì)象轉(zhuǎn)換成字節(jié)序列,并寫(xiě)入到ObjectOutputStream;即使在后面程序中,該對(duì)象的實(shí)例變量發(fā)生了改變,再次調(diào)用WriteObject()方法輸出該對(duì)象時(shí),改變后的實(shí)例變量也不會(huì)被輸出

import java.io.*;

public class SerializeMutable
{
  public static void main(String[] args)
  {

    try(
      // 創(chuàng)建一個(gè)ObjectOutputStream輸入流
      ObjectOutputStream oos = new ObjectOutputStream(
        new FileOutputStream("mutable.txt"));
      // 創(chuàng)建一個(gè)ObjectInputStream輸入流
      ObjectInputStream ois = new ObjectInputStream(
        new FileInputStream("mutable.txt")))
    {
      NbaPlayer player = new NbaPlayer("斯蒂芬?guī)炖?, 30);
      // 系統(tǒng)會(huì)player對(duì)象轉(zhuǎn)換字節(jié)序列并輸出
      oos.writeObject(player);
      // 改變per對(duì)象的name實(shí)例變量
      player.setName("塞斯庫(kù)里");
      // 系統(tǒng)只是輸出序列化編號(hào),所以改變后的name不會(huì)被序列化
      oos.writeObject(player);
      NbaPlayer player1 = (NbaPlayer)ois.readObject();  //①
      NbaPlayer player2 = (NbaPlayer)ois.readObject();  //②
      // 下面輸出true,即反序列化后player1等于player2
      System.out.println(player1 == player2);
      // 下面依然看到輸出"斯蒂芬?guī)炖?,即改變后的實(shí)例變量沒(méi)有被序列化
      System.out.println(player2.getName());
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
  }
}

感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!

相關(guān)文章

  • Java使用Socket判斷某服務(wù)能否連通代碼實(shí)例

    Java使用Socket判斷某服務(wù)能否連通代碼實(shí)例

    這篇文章主要介紹了Java使用Socket判斷某服務(wù)能否連通代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • 關(guān)于springboot加載yml配置文件的no字段自動(dòng)轉(zhuǎn)義問(wèn)題

    關(guān)于springboot加載yml配置文件的no字段自動(dòng)轉(zhuǎn)義問(wèn)題

    這篇文章主要介紹了關(guān)于springboot加載yml配置文件的no字段自動(dòng)轉(zhuǎn)義問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • java判斷字符串是否有逗號(hào)的方法

    java判斷字符串是否有逗號(hào)的方法

    下面小編就為大家?guī)?lái)一篇java判斷字符串是否有逗號(hào)的方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-11-11
  • 使用Feign調(diào)用第三方http接口

    使用Feign調(diào)用第三方http接口

    這篇文章主要介紹了使用Feign調(diào)用第三方http接口,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • java排查一個(gè)線上死循環(huán)cpu暴漲的過(guò)程分析

    java排查一個(gè)線上死循環(huán)cpu暴漲的過(guò)程分析

    這篇文章主要介紹了java排查一個(gè)線上死循環(huán)cpu暴漲的過(guò)程分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-08-08
  • SpringMVC 整合SSM框架詳解

    SpringMVC 整合SSM框架詳解

    這篇文章主要介紹了SpringMVC 整合SSM框架詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 全面解析Java中的GC與幽靈引用

    全面解析Java中的GC與幽靈引用

    一般的應(yīng)用程序不會(huì)涉及到 Reference 編程, 但是了解這些知識(shí)會(huì)對(duì)理解 GC 的工作原理以及性能調(diào)優(yōu)有一定幫助,在實(shí)現(xiàn)一些基礎(chǔ)性設(shè)施比如緩存時(shí)也可能會(huì)用到,希望本文能有所幫助
    2013-09-09
  • IDEA使用JDBC導(dǎo)入配置jar包連接MySQL數(shù)據(jù)庫(kù)

    IDEA使用JDBC導(dǎo)入配置jar包連接MySQL數(shù)據(jù)庫(kù)

    這篇文章介紹了IDEA使用JDBC安裝配置jar包連接MySQL數(shù)據(jù)庫(kù)的方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-12-12
  • Java線程中斷interrupt的常用方法

    Java線程中斷interrupt的常用方法

    本文主要介紹了Java線程中斷interrupt的常用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • 基于Java實(shí)現(xiàn)Socket編程入門(mén)

    基于Java實(shí)現(xiàn)Socket編程入門(mén)

    Java最初是作為網(wǎng)絡(luò)編程語(yǔ)言出現(xiàn)的,使得客戶端和服務(wù)器的溝通變成了現(xiàn)實(shí),而在網(wǎng)絡(luò)編程中,使用最多的就是Socket,本文就來(lái)介紹一下基于Java實(shí)現(xiàn)Socket編程入門(mén),感興趣的可以來(lái)了解一下
    2022-03-03

最新評(píng)論

富蕴县| 盘山县| 邛崃市| 普安县| 兴山县| 温宿县| 上饶市| 宁南县| 元朗区| 久治县| 泰和县| 利川市| 钦州市| 轮台县| 鄱阳县| 太仓市| 嘉定区| 泌阳县| 陕西省| 沂南县| 屏山县| 衡阳市| 土默特右旗| 湾仔区| 兰州市| 三亚市| 萨迦县| 南昌县| 武川县| 新巴尔虎左旗| 平罗县| 霍城县| 扶沟县| 齐河县| 正蓝旗| 司法| 彰武县| 汕头市| 拜泉县| 类乌齐县| 惠州市|