Dieser Vorgang kann auch über das Netzwerk implementiert werden, das zuerst ein Objekt auf dem Windows-Computer erstellen, serialisieren und dann an einen Unix-Computer über das Netzwerk senden und dann genau wieder zusammenmacht. Warum können jeder von RMI, Socket, JMS und EJB Java -Objekte vergehen?
Der Java -Objekt -Serialisierungsmechanismus hat im Allgemeinen zwei Verwendungen:
Java JavaBeans: Die Bean -Status -Informationen werden normalerweise zum Entwurfszeit konfiguriert. .
Mit RMI können Objekte auf Remote -Maschinen wie auf native Maschinen betrieben werden.
Wir können Klassen serialisieren, indem wir die Klassen durch die Implementierung der Schnittstelle java.io.serializable machen. Diese Schnittstelle ist eine Herstellerschnittstelle. Damit die Klasse es implementiert, muss die Schnittstelle keine Methode implementieren. Es wird hauptsächlich verwendet, um Java Virtual Machines (JVMs) darüber zu informieren, dass ein Objekt serialisiert werden muss.
Es gibt einige Punkte, die wir dafür klären müssen:
Nicht alle Klassen können unter CMD serialisiert werden, wir geben Serialver Java.net.socket ein, um Informationen darüber zu erhalten, ob der Sockel serialisierbar ist.
Es gibt viele grundlegende Klassen in Java, die serialisierbare Schnittstellen wie String, Vektor usw. implementiert haben. Zum Beispiel implementiert Hashtable die serialisierbare Schnittstelle nicht.
Es gibt zwei Hauptklassen zum Lesen oder Schreiben von Objekten in Streams: ObjectOutputStream und ObjectInputStream.ObjectOutputStream bietet eine WriteObject -Methode zum Schreiben von Objekten in den Ausgabestream, und ObjectInputStream bietet eine ReadObject -Methode für das Lesen von Objekten aus dem Eingabestrom. Objekte, die diese Methoden verwenden, müssen serialisiert worden sein. Das heißt, die serialisierbare Schnittstelle muss implementiert worden sein. Wenn Sie ein Hashtable -Objekt schreiben möchten, erhalten Sie eine Ausnahme.
Der Prozess der Serialisierung besteht darin, Objekte an Objekte aus dem Byte -Stream zu schreiben und zu lesen. Nachdem Sie den Objektstatus in einen Byte -Stream konvertiert haben, können Sie ihn mit verschiedenen Byte -Stream -Klassen im Java.io -Paket in eine Datei speichern, in einen anderen Thread oder an einen anderen Host über eine Netzwerkverbindung an einen anderen Host senden. Die Objekt -Serialisierungsfunktion ist sehr einfach und leistungsstark und wird in RMI, Socket, JMS und EJB verwendet. Das Objekt -Serialisierungsproblem ist nicht das aufregendste Thema in der Netzwerkprogrammierung, aber es ist sehr wichtig und hat viele praktische Bedeutung.
Die Objektserialisierung kann verteilte Objekte implementieren. Hauptanwendungen wie: RMI verwendet Objektserialisierung, um Dienste auf Remote -Hosts auszuführen, genau wie beim Ausführen von Objekten auf lokalen Maschinen.
Die Serialisierung der Java -Objekte behält nicht nur die Daten eines Objekts bei, sondern speichert auch rekursiv die Daten jedes vom Objekt verwiesenen Objekt. Die gesamte Objekthierarchie kann in einen Byte -Stream geschrieben, in einer Datei gespeichert oder eine Netzwerkverbindung übergeben werden. Die Objektserialisierung kann verwendet werden, um das "tiefe Kopieren" des Objekts durchzuführen, das heißt und das Objekt selbst und das referenzierte Objekt selbst kopieren. Das Serialisieren eines Objekts kann zu der gesamten Folge von Objekten führen.
Die Java -Serialisierung ist relativ einfach und erfordert normalerweise kein Schreiben von maßgeschneidertem Code, um den Objektzustand zu speichern und wiederherzustellen. Klassenobjekte, die die Schnittstelle java.io.Serializable implementieren, können in Byte -Streams konvertiert oder aus Byte -Streams wiederhergestellt werden, ohne der Klasse einen Code hinzuzufügen. Nur in seltenen Fällen sind benutzerdefinierte Code erforderlich, um den Objektzustand zu speichern oder wiederherzustellen. Beachten Sie hier: Nicht jede Klasse kann serialisiert werden, und einige Klassen können beispielsweise nicht serialisiert werden.
Serialisierungsmechanismus:
Die Serialisierung ist in zwei Teile unterteilt: Serialisierung und Deserialisierung. Die Serialisierung ist der erste Teil dieses Prozesses, der die Daten in einen Strom von Bytes für die Speicherung in einer Datei oder Übertragung über ein Netzwerk unterteilt. Die Deserialisierung soll den Byte -Strom öffnen und das Objekt rekonstruieren. Die Objektserialisierung erfordert nicht nur, dass der grundlegende Datentyp in Byte -Darstellung konvertiert wird, sondern manchmal auch die Daten wiederhergestellt. Das Wiederherstellen von Daten erfordert eine Instanz des Objekts, das Daten wiederherstellt. Der Serialisierungsprozess in ObjectOutputStream ist mit einem Byte -Stream verbunden, einschließlich Objekttyp- und Versionsinformationen. Während der Deserialisierung generiert das JVM eine Objektinstanz mit Header -Informationen und kopiert die Daten aus dem Objekt -Byte -Stream in die Objektdatenelemente. Erklären wir es in zwei Teilen:
Verarbeitungsobjektfluss: ( Serialisierungsprozess und Deserialisierungsprozess)
Das Java.io -Paket verfügt über zwei Klassen, die Objekte serialisieren. ObjectOutputStream ist dafür verantwortlich, Objekte in einen Byte -Stream zu schreiben, und ObjectInputStream rekonstruiert Objekte aus einem Byte -Stream.
Lassen Sie uns zunächst die ObjektOutputStream -Klasse verstehen. Die ObjektOutputStream -Klasse erweitert die DataOutput -Schnittstelle.
Die Methode writeObject () ist die wichtigste Methode für die Objektserialisierung. Wenn das Objekt Verweise auf andere Objekte enthält, serialisiert die WriteObject () -Methode diese Objekte rekursiv. Jeder ObjectOutputStream führt eine serialisierte Referenztabelle für Objekte bei, um zu verhindern, dass mehrere Kopien desselben Objekts gesendet werden. (Dies ist wichtig) Da writeObject () den gesamten Satz von kreuzbezogenen Objekten serialisieren kann. Zu diesem Zeitpunkt wird die Antireference -Serialisierung durchgeführt, anstatt erneut in den Objekt -Byte -Stream zu schreiben.
Lassen Sie uns als nächstes die ObjektOutputStream -Klasse aus dem Beispiel verstehen.
Die Codekopie lautet wie folgt:
// Serialisieren Sie das heutige Datum in einer Datei.
FileOutputStream f = new FileOutputStream ("TMP");
ObjectOutputStream S = neuer ObjektOutputStream (f);
S.WriteObject ("Today");
S.WriteObject (neues Datum ());
s.flush ();
Lassen Sie uns nun die ObjectInputStream -Klasse verstehen. Es ähnelt dem ObjektOutputStream. Es erweitert die DataAnput -Schnittstelle. Methoden in ObjectInputStream spiegeln die öffentliche Methode zum Lesen von Java -Grunddatentypen in DataNputStream wider. Die Methode readObject () wird ein Objekt aus einem Byte -Stream deserialisiert. Jedes Mal, wenn die ReadObject () -Methode aufgerufen wird, wird das nächste Objekt im Stream zurückgegeben. Der Objekt -Byte -Stream überträgt den Bytecode der Klasse nicht, sondern enthält den Klassennamen und seine Signatur. Wenn ReadObject () das Objekt empfängt, lädt das JVM die angegebene Klasse im Header. Wenn diese Klasse nicht gefunden werden kann, wirft ReadObject () eine ClassNotFoundException aus. Der Rest der ObjectInputStream -Methoden wird verwendet, um den Deserialisierungsprozess anzupassen.
Beispiele sind wie folgt:
Die Codekopie lautet wie folgt:
// String -Objekte und Datumsobjekte aus der Datei deserialisieren
FileInputStream in = new FileInputStream ("TMP");
ObjectInputStream S = neuer ObjektInputStream (in);
String Today = (String) S.ReadObject ();
Datum Datum = (Datum) s.ReadObject ();
Customisierter Serialisierungsprozess:
Die Serialisierung kann normalerweise automatisch durchgeführt werden, aber manchmal kann der Prozess gesteuert werden. Java kann Klassen als serialisierbar deklarieren, kann jedoch Datenmitglieder, die als statisch oder vorübergehend deklariert sind, manuell steuern.
Beispiel: Eine sehr einfache Serialisierungsklasse.
Die Codekopie lautet wie folgt:
öffentliche Klasse SimpleSerializableClass implementiert serialisierbare {{
String stoday = "heute:";
transientes Datum dttoday = neues Datum ();
}
Bei der Serialisierung sollten alle Datenmitglieder der Klasse serialisierbar sein, mit Ausnahme derjenigen, die als transient oder statisch deklariert sind. Die Erklärung der Variablen als Transient sagt dem JVM, dass wir für die Serialisierung der Argumente verantwortlich sein werden. Nachdem ein Datenmitglied als transient deklariert wurde, kann der Serialisierungsprozess es nicht zum Objekt -Byte -Stream hinzufügen, und es werden keine Daten vom transienten Datenelement gesendet. Bei der Deserialisierung der Daten muss das Datenmitglied rekonstruiert werden (da es Teil der Klassendefinition ist), enthält jedoch keine Daten, da dieses Datenmitglied keine Daten in den Stream schreibt. Denken Sie daran, dass Objektströme nicht statisch oder transient serialisieren. Unsere Klasse muss writeObject () und readObject () -Methoden verwenden, um diese Datenmitglieder zu verarbeiten. Bei Verwendung von WriteObject () und ReadObject () -Methoden sollten Sie auch darauf achten, diese Datenmitglieder in der Reihenfolge zu lesen, die sie geschrieben werden.
Einige der Codes zur Verwendung benutzerdefinierter Serialisierung sind wie folgt
Die Codekopie lautet wie folgt:
// Schreiben Sie die Methode writeObject () um, um die transienten Mitglieder zu verarbeiten.
public void writeObject (ObjectOutputStream OutputStream) löst IoException {aus
outputStream.defaultWriteObject (); // Erstellen Sie die maßgeschneiderte WriteObject () -Methode an
// Verwenden Sie die integrierte Logik in der automatischen Serialisierung.
outputStream.writeObject (osocket.getInetaddress ());
outputStream.writeInt (osocket.getport ());
}
// Schreiben Sie die Methode readObject () um, um transiente Mitglieder zu empfangen.
private void readObject (ObjectInputStream InputStream) löst IOException aus,
ClassNotFoundException {
InputStream.defaultreadObject (); // DefaultreadObject () ergänzt die automatische Serialisierung
Inetaddress oaddress = (inetaddress) InputStream.ReadObject ();
int iport = inputStream.readint ();
osocket = neuer Socket (oaddress, iport);
iid = getId ();
dttoday = new Date ();
}
Passen Sie den Serialisierungsprozess vollständig an:
Wenn eine Klasse vollständig für eine eigene Serialisierung verantwortlich ist, implementiert sie die externalisierbare Schnittstelle anstelle der serialisierbaren Schnittstelle. Die externalisierbare Schnittstellendefinition enthält zwei Methoden writeExternal () und ReadExternal (). Diese Methoden können verwendet werden, um zu steuern, wie Objektdatenelemente in Byte -Streams geschrieben werden. Es gibt überhaupt keine automatische Serialisierung. Achten Sie hier. Die Deklarationsklasse implementiert externe Schnittstellen mit erheblichen Sicherheitsrisiken. Die Methoden writeExternal () und ReadExternal () werden öffentlich deklariert, und böswillige Klassen können diese Methoden verwenden, um Objektdaten zu lesen und zu schreiben. Wenn das Objekt vertrauliche Informationen enthält, seien Sie besonders vorsichtig. Dies beinhaltet die Verwendung sicherer Sockets oder das Verschlüsseln des gesamten Byte -Streams. Zu diesem Zeitpunkt haben wir das Grundwissen der Serialisierung gelernt.