Heim > Java > javaLernprogramm > Hauptteil

Detaillierte Erläuterung der Objektserialisierung und -deserialisierung in Java

高洛峰
Freigeben: 2017-01-18 11:22:16
Original
1402 Leute haben es durchsucht

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. Implementieren Sie Externalizable und definieren Sie die Methoden readExternal und writeExternal.

ObjectOutputStream ruft zuerst die Methode writeExternal der Customer-Klasse auf, um die nicht-transienten Instanzvariablen des Customer-Objekts zu serialisieren übergibt die writeExternal-Methode der Customer-Klasse. Der parameterlose Konstruktor instanziiert ein Objekt und deserialisiert dann die nichtflüchtigen Instanzvariablen des Customer-Objekts.


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.

4. Zusammenfassung

Wenn die Standard-Serialisierungsmethode verwendet wird, können ihre Instanzen serialisiert werden, solange eine Klasse die Serializable-Schnittstelle implementiert. Im Allgemeinen sollten Klassen, die speziell für die Vererbung entwickelt wurden, versuchen, die Serializable-Schnittstelle nicht zu implementieren, da alle ihre Unterklassen ebenfalls serialisierbar sind, sobald die übergeordnete Klasse die Serializable-Schnittstelle implementiert.

Nachteile der Standard-Serialisierungsmethode:

1. Es ist unsicher, sensible Daten von Objekten zu serialisieren, die nicht der Öffentlichkeit zugänglich gemacht werden sollten.

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.

Durch Implementierung des privaten Typs writeObject() und readObject() der Serializable-Schnittstelle oder durch Implementierung der Externalizable-Schnittstelle, Implementierung der Methoden writeExternal() und readExternal() und Bereitstellung von zwei Parameter-losen Konstruktoren des öffentlichen Typs Durch die Steuerung des Serialisierungsprozesses können die Mängel der Standard-Serialisierungsmethode effektiv vermieden werden.

Ich hoffe, dass dieser Artikel für alle bei der Java-Programmierung hilfreich sein wird.

Ausführlichere Artikel zur Objektserialisierung und -deserialisierung in Java finden Sie auf der chinesischen PHP-Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!