JavaRush /Java-Blog /Random-DE /So funktioniert die Serialisierung in Java
ramhead
Level 13

So funktioniert die Serialisierung in Java

Veröffentlicht in der Gruppe Random-DE
In diesem Artikel erklären wir, was Serialisierung ist und wie sie in Java funktioniert. So funktioniert die Serialisierung in Java – 1

Einführung

Bei der Objektserialisierung handelt es sich um die Fähigkeit eines Objekts, eine vollständige Kopie von sich selbst und allen anderen Objekten, auf die es verweist, mithilfe eines Ausgabestreams (z. B. in einer externen Datei) zu speichern. Auf diese Weise kann das Objekt bei Bedarf etwas später aus der serialisierten (gespeicherten) Kopie neu erstellt werden. Die Objektserialisierung, eine neue Funktion, die in JDK 1.1 eingeführt wurde, bietet eine Funktion zum Konvertieren von Gruppen oder einzelnen Objekten in einen Bitstrom oder Byte-Array zur Speicherung oder Übertragung über ein Netzwerk. Und wie bereits erwähnt, kann ein bestimmter Bitstrom oder Byte-Array wieder in Java-Objekte umgewandelt werden. Dies geschieht größtenteils automatisch dank der Klassen ObjectInputStreamund ObjectOutputStream. Der Programmierer kann beschließen, diese Funktionalität zu implementieren, indem er die Schnittstelle Serializablebeim Erstellen der Klasse implementiert. Der Prozess der Serialisierung wird auch als Objekt- Marshalling bezeichnet, während die Deserialisierung als Unmarshaling bezeichnet wird . Serialisierung ist ein Mechanismus, der es einem Objekt ermöglicht, eine Kopie von sich selbst und allen anderen von diesem Objekt referenzierten Objekten in einer externen Datei zu speichern ObjectOutputStream. Die gespeicherten Objekte können Datenstrukturen, Diagramme, Klassenobjekte JFrameoder beliebige andere Objekte sein, unabhängig von ihrem Typ. Gleichzeitig speichert die Serialisierung Informationen über den Typ eines Objekts, sodass diese Informationen später bei der Deserialisierung verwendet werden, um den genauen Objekttyp wiederherzustellen, der es war. Die Serialisierung bietet also die folgenden Funktionen:
  • Ein System zum Speichern von Objekten, d. h. zum Speichern ihrer Eigenschaften in einer externen Datei, auf einem Datenträger oder in einer Datenbank.
  • Remote-Prozeduraufrufsystem.
  • Ein Objektverteilungssystem, beispielsweise in Softwarekomponenten wie COM, COBRA.
  • System zur Identifizierung von Änderungen variabler Daten im Laufe der Zeit.
Um das Konzept der Serialisierung vollständig zu verstehen, müssen Sie die beiden anderen Konzepte – Objektpersistenz und Thread-Persistenz – genau verstehen. Hier werden wir ein wenig über jeden von ihnen sprechen, um uns daran zu erinnern. Eine vollständige Erläuterung dieser Konzepte würde ein eigenes Kapitel für jedes dieser Konzepte erfordern.

Streams:

Jedes Programm muss seine Daten in einen Speicherort oder eine Pipe schreiben und jedes Programm muss Daten aus einer Pipe oder einem Speicherort lesen. In Java werden diese Kanäle, in die Programme schreiben und von denen Programme Daten lesen, Streams( Stream) genannt . So funktioniert die Serialisierung in Java – 2
Abbildung 1. Grafische Darstellung von Threads
Streams werden hauptsächlich in zwei Typen unterteilt:
  • Byte-Stream-Klassen namens *Streams
  • Zeichenstromklassen namens *Reader und *Writer
Jeder Datenschreibstrom enthält eine Reihe von Schreibmethoden. Und jeder Datenlesethread verfügt dementsprechend über ähnliche Lesemethoden. Sobald der Thread erstellt ist, müssen alle diese Methoden aufgerufen werden.

Beharrlichkeit

Unter Objektpersistenz versteht man die Fähigkeit eines Objekts, die Ausführung eines Programms zu „überleben“. Dies bedeutet, dass jedes Objekt, das zur Laufzeit erstellt wurde, vom JVM-Scavenger zerstört wird, wenn dieses Objekt nicht mehr verwendet wird. Wenn jedoch die Persistenz-API implementiert ist, werden diese Objekte nicht vom JVM-Scavenger zerstört, sondern können stattdessen „leben“, was auch den Zugriff auf sie beim nächsten Start der Anwendung ermöglicht. Mit anderen Worten bedeutet Persistenz, dass es eine Lebensdauer für ein Objekt gibt, unabhängig von der Lebensdauer der ausgeführten Anwendung. Eine Möglichkeit, Persistenz zu implementieren, besteht darin, Objekte irgendwo in einer externen Datei oder Datenbank zu speichern und sie dann zu einem späteren Zeitpunkt mithilfe dieser Dateien oder der Datenbank als Quellen wiederherzustellen. Hier kommt die Serialisierung ins Spiel. Jedes nicht persistente Objekt existiert, solange die JVM ausgeführt wird. Serialisierte Objekte sind einfach in Streams umgewandelte Objekte, die dann in einer externen Datei gespeichert oder zur Speicherung und Wiederherstellung über ein Netzwerk übertragen werden.

Implementierung der Serializable-Schnittstelle

Jede Klasse muss eine Schnittstelle implementieren, java.io.Serializableum Objekte dieser Klasse zu serialisieren. Die Schnittstelle Serializableverfügt über keine Methoden und markiert die Klasse nur, damit sie als serialisierbar identifiziert werden kann. Es können nur die Felder eines serialisierten Klassenobjekts gespeichert werden. Methoden oder Konstruktoren werden nicht als Teil des serialisierten Streams gespeichert. Wenn ein Objekt als Referenz auf ein anderes Objekt fungiert, werden die Felder dieses Objekts ebenfalls serialisiert, wenn die Klasse dieses Objekts die Schnittstelle implementiert Serializable. Mit anderen Worten, der so erhaltene Graph dieses Objekts ist vollständig serialisierbar. Ein Objektdiagramm umfasst einen Baum oder eine Struktur von Feldern eines Objekts und seiner Unterobjekte. Zwei Hauptklassen, die bei der Implementierung der Schnittstelle helfen Seriliazable:
  • ObjectInputStream
  • ObjectOutputStream
Listing 1. Beispiel einer einfachen Klasse zur Darstellung der Serialisierung
import java.io.*;
public class RandomClass implements Serializable {
 // Генерация рандомного значения
 private static int r() {
        return (int)(Math.random() * 10);
 }
    private int data[];
    // Конструктор
public RandomClass() {
        datafile = new int[r()];
        for (int i=0; i<datafile.length; i++)
        datafile[i]=r();
 }
    public void printout() {
 System.out.println("This RandomClass has "+datafile.length+" random integers");
 for (int i=0; i<datafile.length; i++) {
        System.out.print(datafile[i]+":");
        System.out.println();
    }
}
Im obigen Code wird eine Klasse erstellt, die serialisierbar ist, weil durch die Serialisierungsschnittstelle „markiert“. Die Klasse erstellt ein Array zufälliger Ganzzahlen, wenn eine Instanz davon erstellt wird. Der folgende Code zeigt die Möglichkeit, mithilfe von Objekte in einen Stream zu schreiben ObjectOutputStream. Das Programm verfügt über ein Array von Ganzzahlen, aber für die Serialisierung müssen wir nicht über seine internen Objekte iterieren. Die Schnittstelle Seriliazableerledigt dies automatisch. Listing 2. Ein einfaches Beispiel für die Serialisierung von Objekten für die Ausgabe in eine Datei
import java.io.*;
import java.util.*;
public class OutSerialize {
    public static void main (String args[]) throws IOException {
        RandomClass rc1 = new RandomClass();
        RandomClass rc2 = new RandomClass();
//создание цепи потоков с потоком вывода ein Objektа в конце
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("objects.dat"));
        Date now = new Date(System.currentTimeMillis());
//java.util.* был импортирован для использования класса Date
        out.writeObject(now);
        out.writeObject(rc1);
        out.writeObject(rc2);
out.close();
        System.out.println("I have written:");
System.out.println("A Date object: "+now);
        System.out.println("Two Group of randoms");
rc1.printout();
rc2.printout();
 }
}
Der folgende Code demonstriert die Fähigkeiten der Klasse ObjectInputStream, die serialisierte Daten aus einer externen Datei in ein Programm einliest. Beachten Sie, dass die Objekte in derselben Reihenfolge gelesen werden, in der sie in die Datei geschrieben wurden. Listing 3. Serialisierte Objekte lesen oder deserialisieren
import java.io.*;
import java.util.*;
public class InSerialize {
 public static void main (String args[]) throws  IOException, ClassNotFoundException {
    ObjectInputStream in =  new ObjectInputStream (new FileInputStream("objects.dat"));
 Date d1 = (Date)in.readObject();
 RandomClass rc1 = (RandomClass)in.readObject();
    RandomClass rc2 = (RandomClass)in.readObject();
    System.out.println("I have read:");
    System.out.println("A Date object: "+d1);
    System.out.println("Two Group of randoms");
    rc1.printout();
rc2.printout();
 }
}
Fast alle Java-Klassen können serialisiert werden, einschließlich AWT-Klassen. Ein Rahmen, bei dem es sich um ein Fenster handelt, enthält eine Reihe grafischer Komponenten. Wenn der Frame serialisiert ist, kümmert sich die Serialisierungs-Engine darum und serialisiert alle seine Komponenten und Daten (Position, Inhalt usw.). Einige Java-Klassenobjekte können nicht serialisiert werden, da sie Daten enthalten, die auf kurzlebige Betriebssystemressourcen verweisen. Zum Beispiel Klassen java.io.FileInputStreamund java.lang.Thread. Wenn ein Objekt Verweise auf nicht serialisierbare Elemente enthält, schlägt der gesamte Serialisierungsvorgang fehl und es wird eine Ausnahme ausgelöst NotSerializableException. Wenn ein Objekt auf eine Referenz eines unserialisierten Objekts verweist, kann es mit dem Schlüsselwort transient serialisiert werden . Listing 4. Serialisierbare Objekte mit dem Schlüsselwort transient erstellen
public class Sclass implements Serializable{
public transient Thread newThread;
//помните, что поток(поток параллельного исполнения) по умолчанию не сериализуемый класс
    private String studentID;
    private int sum;
}

Sicherheit bei der Serialisierung

Bei der Serialisierung einer Klasse in Java werden alle ihre Daten über einen Stream an eine externe Datei oder Datenbank übergeben. Wir können die Daten, die serialisiert werden, jederzeit begrenzen. Hierzu gibt es zwei Möglichkeiten:
  • Jeder als transient deklarierte Klassenparameter wird nicht serialisiert (standardmäßig werden alle Klassenparameter serialisiert).
  • Oder jeder Parameter der Klasse, die wir serialisieren möchten, wird mit einem Tag markiert Externalizable(standardmäßig werden keine Parameter serialisiert).
Ein Datenfeld wird ObjectOutputStreambeim Aufruf für ein Objekt nicht mit serialisiert, wenn das Datenfeld dieses Objekts als transient markiert ist . Zum Beispiel: private transient String password. Um andererseits die Daten eines Objekts explizit als serialisierbar zu deklarieren, müssen wir die Klasse als ExternalizablewriteExternalexplizit readExteranlschreibend und lesend für die Daten dieses Objekts markieren.

Abschluss

Die Funktion der Objektserialisierung wird in vielen verteilten Systemen zur Datenübertragung genutzt. Aber die Serialisierung enthüllt verborgene Details und zerstört so die Authentizität abstrakter Datentypen, was wiederum die Kapselung zerstört. Gleichzeitig ist es schön zu wissen, dass die Daten des serialisierten Objekts dieselben Daten sind, die im ursprünglichen Originalobjekt enthalten waren. Dies ist auch eine großartige Gelegenheit, eine Schnittstelle zu implementieren ObjectInputValidationund eine Methode zu überschreiben validateObject(), selbst wenn mehrere Codezeilen verwendet werden. Wenn das Objekt nicht gefunden wird, können wir entsprechend eine Ausnahme auslösen InvalidObjectException. Originalartikel: So funktioniert die Serialisierung in Java
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION