„Du erinnerst dich bestimmt, dass wir heute das Speichern von Objekten in einer Datei und das Lesen von Objekten aus einer Datei betrachtet haben?“
„Ja, wir haben etwas in einem Ausgabedatenstrom gespeichert und aus einem Eingabedatenstrom gelesen.“
„Sehr gut, Amigo. Toll, dass dir all die Einzelheiten auffallen. Wärst du in der Lage, den Code so zu vervollständigen, dass er in eine Datei speichert und aus einer Datei liest?
„Was vervollständigen?! Deklariere einen FileInputStream und FileOutputStream und übergib diese an die save- und load-Methoden. Das ist gar nicht kompliziert. Total einfach.“
„Ich freue mich für dich. Kommen wir zu einem neuen Thema: Serialisierung.“
Serialisierung ist fast dasselbe wie das, was wir gerade gemacht haben, aber viel cooler und direkt in die Java-Maschine integriert. Die Java-Maschine kann ihre Objekte speichern und laden. Sie braucht nicht einmal Methoden zum Speichern und Laden dafür: Alle Objekte werden innerhalb der Java-Maschine gespeichert, und diese hat vollen Zugriff auf sie.“
Wir nehmen einfach das Objekt und speichern es in einem Stream und lesen aus einem Stream:
public static void main(String[] args) throws Exception
{
Cat cat = new Cat();
//Save a cat to file
FileOutputStream fileOutput = new FileOutputStream("cat.dat");
ObjectOutputStream outputStream = new ObjectOutputStream(fileOutput);
outputStream.writeObject(cat);
fileOutput.close();
outputStream.close();
//Load a cat from file
FileInputStream fiStream = new FileInputStream("cat.dat");
ObjectInputStream objectStream = new ObjectInputStream(fiStream);
Object object = objectStream.readObject();
fiStream.close();
objectStream.close();
Cat newCat = (Cat)object;
}
„Das war‘s?“
„Exakt. Es gibt einen sehr umfangreichen und komplexen Serialisierungsmechanismus, der es uns ermöglicht, in einen Datenstrom zu speichern und aus einem Datenstrom zu lesen. Und das gilt für fast jeden Datentyp.
„Fast jeden. Also nicht für jeden beliebigen Datentyp?“
„Genau, Tatsache ist, dass nicht alle Objekte die inhärente Fähigkeit haben, gespeichert zu werden. Manche Objekte speichern nicht alle ihre Daten intern. Stattdessen verweisen sie lediglich auf andere Objekte und/oder Datenquellen. Zum Beispiel die Konsole (System.in), ein Eingabedatenstrom (InputStream) und andere Dinge.“
Aus diesem Grund haben die Entwickler von Java den speziellen Serializable-Interface-Marker entwickelt. Er wird als Marker bezeichnet, weil er keine Daten und Methoden enthält. Es wird nur zum „Kennzeichnen“ oder „Markieren“ von Klassen verwendet. Wenn wir glauben, dass unsere Klasse alle ihre Daten intern speichert, dann können wir sie mit implements Serializable markieren.
Hier ist ein „Cat“-Beispiel mit Unterstützung für die Serialisierung:
class Cat implements Serializable
{
public String name;
public int age;
public int weight;
}
Wenn wir versuchen, ein Objekt zu serialisieren (zu speichern), prüft die Java-Maschine, ob es die Serialisierung unterstützt: Implementiert es das Serializable-Interface? Wenn dies der Fall ist, dann wird das Objekt gespeichert. Wenn nicht, wird eine Ausnahme ausgelöst, um anzuzeigen, dass eine Serialisierung nicht möglich ist.
Du musst wissen, dass ein serialisierbares Objekt nur aus serialisierbaren Objekten bestehen darf.
„Okay, das ergibt Sinn. Man kann nicht das Ganze speichern, ohne seine Teile zu speichern.“
„So ist es.“
„Und was ist mit ints, Strings und ArrayLists?“
„Sie alle unterstützen die Serialisierung. Die Entwickler von Java haben besonders darauf geachtet, dass dies der Fall ist. Hier sollte es keine Probleme geben.“
Außerdem wird der Typ eines Objekts gespeichert, wenn das Objekt serialisiert wird. Jetzt kannst du eine Referenz auf ein Cat-Objekt in einer Object-Variable speichern. Und alles lässt sich problemlos serialisieren und deserialisieren.
„Deserialisieren?“
„Deserialisierung ist der Vorgang der Umkehrung der Serialisierung: Lesen und Rekonstruieren eines Objekts aus einem Stream/einer Datei.“
„Ah, dann habe ich keine Fragen mehr.“
GO TO FULL VERSION