Die Beispiele in diesem Artikel beschreiben die Objektserialisierung und -deserialisierung in Java. Teilen Sie es als Referenz mit allen. Die Details sind wie folgt:
1. Einführung
Objektserialisierung (serialisierbar) bezieht sich auf den Prozess der Konvertierung eines Objekts in eine Bytesequenz, während Deserialisierung der Prozess der Wiederherstellung eines Objekts basierend auf ist eine Bytefolge.
Serialisierung wird im Allgemeinen in den folgenden Szenarien verwendet:
1. Speichern Sie das Objekt dauerhaft und speichern Sie die Bytesequenz des Objekts in einer lokalen Datei.
2 Netzwerk-Objekte übergeben;
3. Objekte zwischen Prozessen durch Serialisierung übergeben.
Die Klasse, zu der das Objekt gehört, muss die Serializable- oder Externalizable-Schnittstelle implementieren, um serialisiert zu werden. Für Klassen, die die Serializable-Schnittstelle implementieren, wird die Standard-Serialisierungsmethode für die Serialisierung und Deserialisierung verwendet. Die Externalizable-Schnittstelle ist eine Schnittstelle, die die Serializable-Schnittstelle erbt und eine Erweiterung der Serializable-Schnittstelle ist, die die Serialisierung und Deserialisierung vollständig steuert sich selbst. Deserialisierungsverhalten.
Java.io.ObjectOutputStream stellt den Objektausgabestream dar. Seine Methode writeObject(Object obj) kann die Serialisierung des Objekts realisieren und die erhaltene Bytesequenz in den Zielausgabestream schreiben.
Java.io.ObjectInputStream stellt den Objekteingabestream dar. Seine readObject()-Methode kann die Bytesequenz aus dem Quelleingabestream lesen, sie in ein Objekt deserialisieren und zurückgeben.
2. Mehrere Serialisierungsmethoden
Angenommen, eine Kundenklasse ist definiert. Abhängig von der Art und Weise, wie der Kunde die Serialisierung implementiert, gibt es möglicherweise die folgenden Serialisierungsmethoden:
1. Implementieren Sie serialisierbare, undefinierte readObject- und writeObject-Methoden
ObjectOutputStream verwendet die JDK-Standardmethode, um nicht-transiente Instanzvariablen des Kundenobjekts zu serialisieren.
ObjectInputStream verwendet die JDK-Standardmethode, um die nicht-transienten Instanzvariablen von zu serialisieren Das Kundenobjekt Die Instanzvariablen werden deserialisiert.
2. Implementieren Sie Serializable und definieren Sie die Methoden readObject und writeObject
ObjectOutputStream ruft die Methode writeObject (ObjectOutputStream out) der Customer-Klasse auf, um die nicht-transienten Instanzvariablen des Customer-Objekts zu serialisieren; 🎜 >ObjectInputStream ruft die readObject(ObjectInputStream in)-Methode der Customer-Klasse auf, um die nicht-transienten Instanzvariablen des Customer-Objekts zu deserialisieren.
3. Serialisierbare Schnittstelle
Die Klasse implementiert die java.io.Serializable-Schnittstelle, um ihre Serialisierungsfunktion zu aktivieren. Eine Klasse, die diese Schnittstelle nicht implementiert, kann keinen ihrer Zustände serialisieren oder deserialisieren. Alle Untertypen einer serialisierbaren Klasse sind selbst serialisierbar. Die Serialisierungsschnittstelle verfügt über keine Methoden oder Felder und wird nur zur Identifizierung serialisierbarer Semantik verwendet.
Während der Deserialisierung werden Felder einer nicht serialisierbaren Klasse mit dem öffentlichen oder geschützten parameterlosen Konstruktor der Klasse initialisiert. Serialisierbare Unterklassen müssen Zugriff auf den parameterlosen Konstruktor haben. Felder serialisierbarer Unterklassen werden aus diesem Stream wiederhergestellt.
Beim Durchlaufen einer Klassenansicht stoßen Sie möglicherweise auf Objekte, die die Serializable-Schnittstelle nicht unterstützen. In diesem Fall wird eine NotSerializableException ausgelöst und die Klasse des nicht serialisierbaren Objekts identifiziert.
1. Genaue Signatur
Klassen, die während der Serialisierung und Deserialisierung eine besondere Behandlung erfordern, müssen die folgende genaue Signatur verwenden, um spezielle Methoden zu implementieren:
private void writeObject( java.io. ObjectOutputStream out) löst eine IOException aus
private void readObject(java.io.ObjectInputStream in) löst eine IOException aus, ClassNotFoundException;private void readObjectNoData() löst eine ObjectStreamException aus;
writeObject-Methode ist für das Schreiben des Zustands verantwortlich ein Objekt einer bestimmten Klasse, damit die entsprechende readObject-Methode es wiederherstellen kann. Der Standardmechanismus zum Speichern der Felder eines Objekts kann durch Aufrufen von out.defaultWriteObject aufgerufen werden. Die Methode selbst muss keinen Zustand beinhalten, der zu ihrer Oberklasse oder Unterklasse gehört. Der Status kann gespeichert werden, indem einzelne Felder mithilfe der writeObject-Methode oder mithilfe der von DataOutput für primitive Datentypen unterstützten Methoden in einen ObjectOutputStream geschrieben werden.
Die readObject-Methode ist für das Lesen und Wiederherstellen von Klassenfeldern aus dem Stream verantwortlich. Es kann in.defaultReadObject aufrufen, um den Standardmechanismus zum Wiederherstellen der nicht statischen und nicht vorübergehenden Felder des Objekts aufzurufen. Die Methode „defaultReadObject“ verwendet Informationen aus dem Stream, um die Felder des Objekts im Stream zuzuordnen, die von den entsprechenden angegebenen Feldern im aktuellen Objekt gehalten werden. Dies wird verwendet, um Situationen zu bewältigen, in denen nach der Weiterentwicklung der Klasse neue Felder hinzugefügt werden müssen. Die Methode selbst muss keinen Zustand beinhalten, der zu ihrer Oberklasse oder Unterklasse gehört. Der Status kann gespeichert werden, indem einzelne Felder mithilfe der writeObject-Methode oder mithilfe der von DataOutput für primitive Datentypen unterstützten Methoden in einen ObjectOutputStream geschrieben werden.
Die readObjectNoData-Methode ist für die Initialisierung des Objektstatus einer bestimmten Klasse verantwortlich, wenn der Serialisierungsstream die angegebene Klasse nicht als Superklasse des zu deserialisierenden Objekts auflistet. Dies tritt auf, wenn der Empfänger eine andere Version der deserialisierten Instanzklasse verwendet als der Sender und die Version des Empfängers eine Klasse erweitert, die nicht durch die Version des Senders erweitert wird. Dies tritt auch auf, wenn der Serialisierungsstream manipuliert wurde. Daher kann die Methode readObjectNoData verwendet werden, um das deserialisierte Objekt korrekt zu initialisieren, unabhängig davon, ob der Quellstream „feindlich“ oder unvollständig ist.
Wenn Sie ein Objekt in einen Stream schreiben, müssen Sie die serialisierbare Klasse des zu verwendenden Ersatzobjekts angeben. Diese spezielle Methode sollte mit der genauen Signatur implementiert werden:
ANY-ACCESS-MODIFIER-Objekt writeReplace( ) löst eine ObjectStreamException aus;
Diese writeReplace-Methode wird durch Serialisierung aufgerufen, wenn diese Methode vorhanden ist und über eine in der Klasse des zu serialisierenden Objekts definierte Methode auf sie zugegriffen werden kann. Daher kann die Methode privaten, geschützten und paketprivaten Zugriff haben. Der Zugriff auf diese Methode durch Unterklassen folgt Java-Zugriffsregeln.
Wenn Sie eine Instanz einer Klasse aus einem Stream lesen, müssen Sie die genaue Signatur angeben, die die alternative Klasse verwenden soll, um diese spezielle Methode zu implementieren.
ANY-ACCESS-MODIFIER-Objekt readResolve() löst ObjectStreamException aus;
Diese readResolve-Methode folgt denselben Aufrufregeln und Zugriffsregeln wie writeReplace.
Wenn eine Klasse die readResolve-Methode definiert, wird die readResolve-Methode am Ende der Deserialisierung aufgerufen und das von dieser Methode zurückgegebene Objekt ist das Endergebnis der Deserialisierung.
2.serialVersionUID
Die Serialisierungslaufzeit verwendet eine Versionsnummer namens serialVersionUID, um sie jeder serialisierbaren Klasse zuzuordnen. Diese wird verwendet, um die Reihenfolge während des Deserialisierungsprozesses zu überprüfen. Ob der Sender und der Empfänger einer Serialisierung Das Objekt hat eine serialisierungskompatible Klasse für das Objekt geladen. Wenn sich die serialVersionUID der vom Empfänger geladenen Objektklasse von der entsprechenden Versionsnummer der Absenderklasse unterscheidet, führt die Deserialisierung zu einer InvalidClassException. Eine serialisierbare Klasse kann ihre eigene serialVersionUID explizit deklarieren, indem sie ein Feld mit dem Namen „serialVersionUID“ deklariert (das ein statisches, letztes langes Feld sein muss):
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
Wenn eine serialisierbare Klasse Die Klasse deklariert nicht explizit eine serialVersionUID. Die Serialisierungslaufzeit berechnet einen Standardwert für die serialVersionUID für die Klasse basierend auf Aspekten der Klasse, wie in der „Java(TM) Object Serialization Specification“ angegeben. Es wird jedoch dringend empfohlen, dass alle serialisierbaren Klassen explizit einen SerialVersionUID-Wert deklarieren, da die Berechnung der Standard-SerialVersionUID sehr empfindlich auf die Details der Klasse reagiert und je nach Compiler-Implementierung stark variieren kann, sodass während des Deserialisierungsprozesses eine unerwartete InvalidClassException auftreten kann. Um die Konsistenz der serialVersionUID-Werte über verschiedene Java-Compiler-Implementierungen hinweg sicherzustellen, müssen Serialisierungsklassen daher einen expliziten serialVersionUID-Wert deklarieren. Es wird außerdem dringend empfohlen, serialVersionUID explizit mit dem privaten Modifikator zu deklarieren (wenn möglich), da eine solche Deklaration nur in direkt deklarierenden Klassen verwendet werden sollte – das Feld serialVersionUID ist als geerbtes Mitglied nutzlos. Array-Klassen können keine explizite serialVersionUID deklarieren, daher verfügen sie immer über einen berechneten Standardwert. Es besteht jedoch keine Anforderung, dass Array-Klassen mit dem Wert serialVersionUID übereinstimmen.
3.Externalizable-Schnittstelle
Externalizable ist eine Erweiterung von Serailizable. Die Serialisierung einer Klasse, die die Externalizable-Schnittstelle implementiert, weist die folgenden Merkmale auf:
Rufen Sie die Klassenmethode writeExternal während der Serialisierung und des Aufrufs auf Bei der Deserialisierung ruft die readExternal-Methode zunächst den Parameterlosen-Konstruktor auf. Dies unterscheidet sich von der Standard-Deserialisierung. Daher muss für die Implementierung der Serialisierung eine Klasse bereitgestellt werden Parameterloser Konstruktor, andernfalls tritt während der Deserialisierung eine Ausnahme auf.
Das ist nicht der Fall Überprüfen Sie, ob die Mitgliedsvariablen des Objekts die richtigen Einschränkungen erfüllen und die Daten möglicherweise manipuliert werden, was zu einer abnormalen Operation führt.
3 Wenn das Objektdiagramm sehr komplex ist, ist dies der Fall verbrauchen viele Ressourcen und die Einstellung führt zu einem Java-Stack-Überlauf der virtuellen Maschine.
4 Machen Sie die Schnittstelle der Klasse durch die interne Implementierung der Klasse eingeschränkt, was die Aktualisierung und Wartung der Klasse einschränkt.