Java オブジェクトのシリアル化 NIO NIO2 の詳細な紹介と分析

黄舟
リリース: 2017-03-06 10:44:11
オリジナル
1360 人が閲覧しました

この記事では、主に Java Object Serialization NIO NIO2 の詳細な紹介と分析を紹介します。シリアル化メカニズムにより、オブジェクトはプログラムの実行とは独立して存在できます。必要な方は、

Java Object Serialization NIO の詳細な紹介と分析を参照してください。 NIO2

概要:

オブジェクトのシリアル化

オブジェクトのシリアル化メカニズムにより、メモリ内の Java オブジェクトをプラットフォームに依存しないバイナリ ストリームに変換でき、ディスクに保存したり、ネットワークや他のプログラムを介して送信したりできます。このバイナリ ストリームを取得した後、元の Java オブジェクトに復元できます。 シリアル化メカニズムにより、プログラムの実行とは独立してオブジェクトが存在できるようになります

シリアル化の意味と意味

シリアル化

シリアル化メカニズムにより、オブジェクトがプログラムの実行とは独立して存在できるようになります

シリアル化(Serialize) ) ) は、Java オブジェクトを IO ストリームに書き込むことを指します。同様に、オブジェクトの逆シリアル化 (Deserialize) は、IO ストリームから Java オブジェクトを回復することを指します

オブジェクトにシリアル化メカニズムをサポートさせる必要がある場合、そのクラスはクラスをシリアル化可能にするには、次の 2 つのインターフェイスのいずれかを実装する必要があります:

  • Serializable: このクラスのインスタンスを実装するためのメソッドを実装する必要がないことを示します。シリアル化可能

  • 外部化可能

ネットワーク経由で送信されるすべてのオブジェクトはシリアル化可能である必要があります。そうでない場合、ディスクに保存する必要があるすべてのオブジェクトはシリアル化可能である必要があります。プログラムによって作成される各 JavaBean クラスはシリアル化可能を実装します。 ;

シリアル化を実装するためにオブジェクト ストリームを使用する

シリアル化を実装するシリアル化可能なクラスを実装する プログラムは次の 2 つの手順でオブジェクトをシリアル化できます。

1. この出力ストリームは処理ストリームであるため、他のノード ストリームに基づく必要があります

// 创建个ObjectOutputStream输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt"));
ログイン後にコピー

2. ObjectOutputStream オブジェクトの writeObject メソッドを呼び出して、シリアル化可能なオブジェクトを出力します

// 将一个Person对象输出到输出流中
oos.writeObject(per);
ログイン後にコピー

NbaPlayer クラスを定義し、そのオブジェクトを識別する Serializable インターフェイスを実装します。このクラスはシリアル化可能です

public class NbaPlayer implements java.io.Serializable
{
  private String name;
  private int number;
  // 注意此处没有提供无参数的构造器!
  public NbaPlayer(String name, int number)
  {
    System.out.println("有参数的构造器");
    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 を使用して NbaPlayer オブジェクトをディスク ファイルに書き込みます

import java.io.*;

public class WriteObject
{
  public static void main(String[] args)
  {
    try(
      // 创建一个ObjectOutputStream输出流
      ObjectOutputStream oos = new ObjectOutputStream(
        new FileOutputStream("object.txt")))
    {
      NbaPlayer player = new NbaPlayer("维斯布鲁克", 0);
      // 将player对象写入输出流
      oos.writeObject(player);
    }
    catch (IOException ex)
    {
      ex.printStackTrace();
    }
  }
}
ログイン後にコピー

逆シリアル化

バイナリ ストリームから Java オブジェクトを復元するには、逆シリアル化を使用する必要がありますプログラムは次の 2 つの手順でオブジェクトをシリアル化できます:

1. ObjectInputStream 入力ストリームを作成するため、他のノード ストリームに基づいて構築する必要があります

2. ObjectInputStream オブジェクトの readObject() メソッドを呼び出して、ストリーム内のオブジェクトを読み取ります。このメソッドは、実際の型にキャストできる Object 型の Java オブジェクトを返します

// 创建个ObjectInputStream输出流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.txt"));
ログイン後にコピー

NbaPlayer オブジェクトを読み取る手順object.txt ファイルから

// 从输入流中读取一个Java对象,并将其强制类型转换为Person类
Person p = (Person)ois.readObject();
ログイン後にコピー

逆シリアル化は、Java クラスではなく Java オブジェクトのデータのみを読み取ります。そのため、逆シリアル化を使用して Java オブジェクトを復元する場合は、Java オブジェクトが属するクラス ファイルを指定する必要があります。 ClassNotFoundException 例外がスローされます。逆シリアル化メカニズムは、コンストラクターを通じて Java オブジェクトを初期化する必要はありません

シリアル化メカニズムを使用してファイルに書き込む場合、複数の Java オブジェクトが入力され、逆シリアル化メカニズムを使用してオブジェクトが復元される必要があります。実際に書かれた順に読んでください。シリアル化可能なクラスに複数の親クラス (直接の親クラスと間接的な親クラスを含む) がある場合、これらの親クラスは引数のないコンストラクターを持つか、シリアル化可能です。そうでない場合は、逆シリアル化によって InvalidClassException がスローされます。親クラスがシリアル化可能でなく、パラメーターなしのコンストラクターのみを持つ場合、親クラスによって定義された Field 値はバイナリ ストリームにシリアル化されません

オブジェクト参照のシリアル化

クラスの Field 型が基本でない場合type または String 型で、別の参照型である場合、この参照型はシリアル化可能である必要があります。そうでない場合、この型のフィールドを使用するクラスもシリアル化可能ではありません

import java.io.*;
public class ReadObject
{
  public static void main(String[] args)
  {
    try(
      // 创建一个ObjectInputStream输入流
      ObjectInputStream ois = new ObjectInputStream(
        new FileInputStream("object.txt")))
    {
      // 从输入流中读取一个Java对象,并将其强制类型转换为NbaPlayer类
      NbaPlayer player = (NbaPlayer)ois.readObject();
      System.out.println("名字为:" + player.getName()
        + "\n号码为:" + player.getNumber());
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
  }
}
ログイン後にコピー

Java 特別シリアル化アルゴリズム

    すべてディスクに保存されたオブジェクトにはシリアル化番号があります
  • プログラムがオブジェクトをシリアル化しようとすると、プログラムはまずオブジェクトがシリアル化されているかどうかを確認し、そのオブジェクトが (この仮想マシン内で) 一度もシリアル化されていない場合にのみ、システムオブジェクトをバイトシーケンスに変換して出力します
  • オブジェクトがシリアル化されている場合、プログラムはオブジェクトを再度シリアル化するのではなく、シーケンス番号を直接出力します

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;
  }
}
ログイン後にコピー

4つのオブジェクトが書き込まれました出力ストリームに送信すると、実際にシリアル化されたのは 3 つだけであり、シーケンスの 2 つの AllStar オブジェクトのプレーヤー参照は実際には同じ NbaPlayer オブジェクトでした。次のプログラムは、シリアル化されたファイル内のオブジェクトを読み取ります

import java.io.*;
public class WriteAllStar
{
  public static void main(String[] args)
  {
    try(
      // 创建一个ObjectOutputStream输出流
      ObjectOutputStream oos = new ObjectOutputStream(
        new FileOutputStream("allStar.txt")))
    {
      NbaPlayer player = new NbaPlayer("詹姆斯哈登", 13);
      AllStar allStar1 = new AllStar("西部全明星", player);
      AllStar allStar2 = new AllStar("首发后卫", player);
      // 依次将四个对象写入输出流
      oos.writeObject(allStar1);
      oos.writeObject(allStar2);
      oos.writeObject(player);
      oos.writeObject(allStar2);
    }
    catch (IOException ex)
    {
      ex.printStackTrace();
    }
  }
}
ログイン後にコピー

同じ変数Javaオブジェクトが複数回シリアル化された場合、最初のシリアル化のみがJavaオブジェクトをバイト列に変換して出力します

当使用Java序列化机制序列化可变对象时,只有第一次调用WriteObject()方法来输出对象时才会将对象转换成字节序列,并写入到ObjectOutputStream;即使在后面程序中,该对象的实例变量发生了改变,再次调用WriteObject()方法输出该对象时,改变后的实例变量也不会被输出

import java.io.*;

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

    try(
      // 创建一个ObjectOutputStream输入流
      ObjectOutputStream oos = new ObjectOutputStream(
        new FileOutputStream("mutable.txt"));
      // 创建一个ObjectInputStream输入流
      ObjectInputStream ois = new ObjectInputStream(
        new FileInputStream("mutable.txt")))
    {
      NbaPlayer player = new NbaPlayer("斯蒂芬库里", 30);
      // 系统会player对象转换字节序列并输出
      oos.writeObject(player);
      // 改变per对象的name实例变量
      player.setName("塞斯库里");
      // 系统只是输出序列化编号,所以改变后的name不会被序列化
      oos.writeObject(player);
      NbaPlayer player1 = (NbaPlayer)ois.readObject();  //①
      NbaPlayer player2 = (NbaPlayer)ois.readObject();  //②
      // 下面输出true,即反序列化后player1等于player2
      System.out.println(player1 == player2);
      // 下面依然看到输出"斯蒂芬库里",即改变后的实例变量没有被序列化
      System.out.println(player2.getName());
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
  }
}
ログイン後にコピー

以上就是Java 对象序列化 NIO NIO2详细介绍及解析的内容,更多相关内容请关注PHP中文网(www.php.cn)!


関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート