Heim  >  Artikel  >  Java  >  Detaillierte Erläuterung der Java-Objektserialisierung NIO NIO2

Detaillierte Erläuterung der Java-Objektserialisierung NIO NIO2

高洛峰
高洛峰Original
2017-02-27 15:43:461424Durchsuche

Detaillierte Einführung und Analyse der Java-Objektserialisierung NIO NIO2

Zusammenfassung:

Objektserialisierung

Der Objektserialisierungsmechanismus ermöglicht die Konvertierung von Java-Objekten im Speicher in plattformunabhängige Binärströme, die auf der Festplatte gespeichert oder über das Netzwerk übertragen werden können. Andere Programme können den Binärstrom nach dem Abrufen in seinen ursprünglichen Zustand zurückversetzen es. Java-Objekt. Der Serialisierungsmechanismus ermöglicht die Existenz von Objekten unabhängig von der Ausführung des Programms

Die Bedeutung und Bedeutung der Serialisierung

Serialisierung

Der Serialisierungsmechanismus kann dies ermöglichen Das Objekt muss unabhängig von der Ausführung des Programms existieren

Serialisierung (Serialisieren) bezieht sich auf das Schreiben eines Java-Objekts in den E/A-Stream. Entsprechend bezieht sich die Deserialisierung (Deserialisieren) des Objekts auf die Deserialisierung aus dem E/A-Stream . Stellen Sie das Java-Objekt im Stream wieder her

Wenn Sie dafür sorgen müssen, dass ein Objekt den Serialisierungsmechanismus unterstützt, muss seine Klasse serialisierbar sein. Um eine Klasse serialisierbar zu machen, müssen Sie Folgendes implementieren: Eine der beiden Schnittstellen :

  • Serialisierbar: Die Implementierung dieser Schnittstelle erfordert keine Implementierung von Methoden, sie zeigt lediglich an, dass Instanzen dieser Klasse serialisierbar sind

  • Externalisierbar

Alle über das Netzwerk übertragenen Objekte sollten serialisierbar sein, andernfalls tritt eine Ausnahme auf. Alle Objekte, die auf der Festplatte gespeichert werden müssen, müssen serialisierbar sein erstellt vom Programm implementiert Serializable;

Verwenden Sie den Objektstrom, um die Serialisierung zu implementieren

Eine Klasse, die Serializable implementiert, um die Serialisierung zu implementieren. Das Programm kann das Objekt über die folgenden beiden serialisieren Schritte:

1. Dieser Ausgabestream ist ein Verarbeitungsstream, daher muss er auf der Grundlage anderer Knotenstreams erstellt werden

// 创建个ObjectOutputStream输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt"));

2. Rufen Sie die writeObject-Methode des ObjectOutputStream-Objekts auf, um das serialisierbare Objekt auszugeben.

// 将一个Person对象输出到输出流中
oos.writeObject(per);

Definition Eine NbaPlayer-Klasse, die die Serializable-Schnittstelle implementiert , das Objekte dieser Klasse als serialisierbar identifiziert

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;
  }
}

Verwenden Sie ObjectOutputStream, um ein NbaPlayer-Objekt in die Festplattendatei zu schreiben

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();
    }
  }
}

Deserialisierung

Um Java-Objekte aus einem Binärstream wiederherzustellen, müssen Sie Deserialisierung verwenden. Das Programm kann das Objekt über die folgenden beiden serialisieren Schritte:

1. Erstellen Sie einen ObjectInputStream-Eingabestream. Dieser Eingabestream ist ein Verarbeitungsstream und muss daher auf der Grundlage anderer Knotenstreams erstellt werden

// 创建个ObjectInputStream输出流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.txt"));

2. Rufen Sie die readObject()-Methode des ObjectInputStream-Objekts auf, um die Objekte im Stream zu lesen. Diese Methode gibt ein Java-Objekt vom Typ Object zurück, das in seinen wahren Typ umgewandelt werden kann 🎜>

// 从输入流中读取一个Java对象,并将其强制类型转换为Person类
Person p = (Person)ois.readObject();
Schritte zum Lesen des NbaPlayer-Objekts aus der object.txt-Datei

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();
    }
  }
}
Deserialisierung liest nur die Daten von Java-Objekten, nicht von Java-Klassen. Wenn Sie die Deserialisierung zum Wiederherstellen von Java-Objekten verwenden, müssen Sie daher die Klassendatei angeben, zu der das Java-Objekt gehört, da sonst eine ClassNotFoundException-Ausnahme auftritt um das Java-Objekt über den Konstruktor zu initialisieren

Wenn mehrere Java-Objekte mithilfe des Serialisierungsmechanismus in die Datei geschrieben werden, muss der Deserialisierungsmechanismus verwendet werden, um das Objekt gemäß dem tatsächlich geschriebenen Lesevorgang nacheinander wiederherzustellen. Wenn eine serialisierbare Klasse mehrere übergeordnete Klassen hat (einschließlich direkter übergeordneter Klassen und indirekter übergeordneter Klassen), haben diese übergeordneten Klassen entweder Konstruktoren ohne Argumente oder sind ebenfalls serialisierbar – andernfalls löst die Deserialisierung eine InvalidClassException aus. Wenn die übergeordnete Klasse nicht serialisierbar ist und nur über einen Konstruktor ohne Parameter verfügt, wird der von der übergeordneten Klasse definierte Feldwert nicht in den Binärstrom

Serialisierung von Objektreferenzen

Wenn der Feldtyp einer Klasse kein Basistyp oder String-Typ, sondern ein anderer Referenztyp ist, muss dieser Referenztyp serialisierbar sein, andernfalls kann die Klasse, die ein Feld dieses Typs verwendet, nicht serialisiert werden

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;
  }
}
Spezieller Java-Serialisierungsalgorithmus

Alle auf der Festplatte gespeicherten Objekte haben eine Serialisierungsnummer

  • Wenn das Programm versucht, ein Objekt zu serialisieren, prüft das Programm zunächst, ob das Objekt serialisiert wurde. Nur wenn das Objekt noch nie (in dieser virtuellen Maschine) serialisiert wurde, konvertiert das System das Objekt in eine Bytefolge umwandeln und ausgeben

  • Wenn ein Objekt serialisiert wurde, gibt das Programm einfach direkt eine Serialisierungsnummer aus, anstatt das Objekt erneut zu reserialisieren


4 Schreibausgänge Es sind tatsächlich nur drei Stream-Objekte serialisiert, und die Player-Referenzen der beiden AllStar-Objekte in der Sequenz sind tatsächlich dasselbe NbaPlayer-Objekt . Das folgende Programm liest Objekte in einer serialisierten Datei
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();
    }
  }
}

Wenn dasselbe veränderbare Java-Objekt mehrmals serialisiert wird, wird nur das erste Mal serialisiert. Erst dann wird es serialisiert Das Java-Objekt wird in eine Bytefolge umgewandelt und ausgegeben
import java.io.*;
public class ReadAllStar
{
  public static void main(String[] args)
  {
    try(
      // 创建一个ObjectInputStream输出流
      ObjectInputStream ois = new ObjectInputStream(
        new FileInputStream("allStar.txt")))
    {
      // 依次读取ObjectInputStream输入流中的四个对象
      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是否是同一个对象:"
        + (star2 == star3));
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
  }
}

当使用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中文网!


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn