Java Grundkurs 3: Generische Programmierung, Datenströme, Datumsrechnung

Serializable und die SerialVersionUID

LinkedIn Learning kostenlos und unverbindlich testen!

Jetzt testen Alle Abonnements anzeigen
In diesem Video lernen Sie die Voraussetzung kennen, die eine Klasse mitbringen muss, damit ihr Objekt in einen Datenstrom geschrieben werden kann: Dabei handelt es sich um das Interface Serializable, das die Klasse implementieren muss, damit ihr Objekt serialisierbar ist. Außerdem erklärt Ihnen der Trainer, dass eine serialisierbare Klasse eine SerialVersionUID enthalten muss, damit das hieraus erzeugte Objekt versionsübergreifend einlesbar ist.

Transkript

Bislang haben wir Eingabe- und Ausgabeströme verwendet, um einzelne Bytes oder Zeichen einzulesen oder zu schreiben. Man könnte sich nun vorstellen, dass es doch eigentlich kein Problem sein müsste, auch eine Instanz eines Kunden als Menge von Bytes auf der Festplatte zu speichern. Das wäre doch eigentlich praktisch. Wenn wir das Programm zu einem anderen Zeitpunkt erneut öffnen, könnten wir das Objekt wieder einlesen und hätten wieder genau den Zustand, der einstmals abgelegt wurde. Und genau das dachten sich auch die Konstrukteure von Java, als Java erstmalig erfunden wurde. Denn sie hatten das Ziel, dass nicht nur Java Klasen und Java Bibliotheken aus dem Internet heruntergeladen werden konnten, sondern dass auch Objekte von Gerät zu Gerät versendet werden können. Auf diese Weise spielt es dann keine Rolle mehr, auf welchem Gerät man sich die Ergebnisse beziehungsweise den Zustand der Objekte gerade betrachtet. Die Geräte sollten auf unkomplizierte Art und Weise den gleichen Zustand haben. In diesem Video werde ich Ihnen zeigen, welche Voraussetzungen eine Klasse hierfür mitbringen muss, damit ihre Objekt speicherbar sind. Zunächst einmal benötigen wir eine Klasse, um hieraus Objekte zu erzeugen. Ich definiere also eine neue Klasse, die ich Katze nennen werde. Hierfür gehe ich ins Hauptmenü auf File, dann auf New, dann auf Class und das Package Dafür erzeuge ich ein neues Package, unterhalb von BMI, also unterhalb von de.java2enterprise.bmi. Darunter setze ich einen weiteren Pfad mit model und die Klasse, die nenne ich Katze und bestätige mit Finish. So jetzt brauchen wir zwei Attribute. Die sind beide vom Wrapper Typ Double. Einmal die Groesse der Katze und dann auch noch das Gewicht. Dann brauchen wir auch noch Setter und Getter. Die erzeuge ich, indem ich mir von Eclipse helfen lasse. So, nach Gewicht sollen die erzeugt werden, die neuen Methoden und dann bin ich damit fertig. Was nun für die Speicherung der Objekte wichtig ist, dass die Klasse Katze in einen Datenstrom geschickt werden kann. Der Fachausdruck hierfür lautet serialisierbar. Unserer Klasse Katze muss hierfür das Interface Serializable implementieren. Also implementiere ich dieses Interface. Katze Implements Serializable. Und das war es schon fast, damit die Objekte der Klasse Katze speicherbar sind. Denn damit das Schreibe und das Lesen gelingt, stellt die Laufzeitumgebung diese eine Bedingung und das ist eben, dass die Klasse dessen Objekt serialisiert werden soll, das Interface Serializable implementiert. Aber das ist noch nicht alles, denn wenn das Objekt, das serialisiert werden soll eines komplexen Datentyps enthält, müssen auch die hiermit betroffenen Klassen das Interface Serializable implementieren. Wenn wir an dieser Stelle hier elementare Datentypen verwendet hätten, gäbe es dieses Problem nicht. Aber bei einer Klasse müssen wir sicherstellen, dass auch sie das Interface Serializable implementiert. Also halte die Steuerungs-Taste gedrückt und klicke mit der Maus auf den Bezeichner Double und schaue mir hier den Quelltext an. Und wie Sie sehen, implementiert die Klasse Double das Interface Serializable nicht. Aber die Klasse implementiert oder erweitert die Klasse Number. Aber vielleicht implementiert diese ja das Interface Serializable. Also halte ich die Steuerungs-Taste wieder gedrückt und klicke auf Number und schaue dort nach. Und siehe da, die Klasse Number implementiert das Interface Serializable, sodass auch alle implementierenden Abkommen serialisierbar sind. Wie das Serialisieren bei Java eine bedeutende Rolle spielt, wurden insgesamt sehr gängige Klassen von Java bereits mit diesem Interface versehen. Beispielsweise implementieren alle Wrapper Klassen und die Klasse String das Interface Serializable. Andererseits gibt es auch Klassen aus der Standardbibliothek, die nicht serialisierbar sind. Dabei handelt es sich um Klassen, die bei einer Serialisierung Problem zur Laufzeit verursachen könnten. File Input Stream ist ein Beispiel für eine solche Klasse. Aber kommen wir zurück zur Klasse Katze. Hier sehen Sie nun, dass uns Eclipse mit einer Warnung auf ein Problem hinweist. Denn wenn ich die Maus über den Klassenbezeichner halte, erhalte ich diese Meldung hier, The srializable class Katze does not declare a static final serialVersionUID Field of type long. Hiermit weist mich Eclipse darauf hin, dass eine serialisierbare Klasse, eine Klassenvariable mit dem Namen serialVersionUID enthalten sollte. Und jetzt erkläre ich Ihnen, wofür wir eine serialVersionUID benötigen. Und zwar hat dies hiermit zu tun, dass es von unserer Katzenklasse unterschiedliche Versionen geben könnte. Und da stellt sich die Frage, wie ich festlegen kann, dass ein Objekt, das ich mal mit einer älteren Katzenversion abgespeichert habe, mit der neueren Katzenversion kompatibel ist. In einer neueren Version könnte ich also bei der Klasse Katze eine Objektvariable des Typs String einbauen, um der Katze einen Namen zu geben, beispielsweise so. Und dann braucht der String natürlich String Name auch Getter und Setter und den füge ich hier direkt hinter Gewicht füge ich die Methoden dann ein. Die sehen Sie jetzt hier. Und jetzt hat die Katze auch noch ein drittes Attribut erhalten und jetzt stellt sich die Frage, was nun passieren würde, wenn man ehemals ein Objekt abgespeichert hätte und nun mit der aktuellen Version, die ja über ein weiteres Attribut verfügt, was dann passieren würde, wenn ich das Objekt mit dieser Klasse einlese. Und die Antwort lautet wie folgt. Ohne serialVersionUID würde die Zuordnung des alten Objekts nicht gelingen. Denn Java vergleicht das gespeicherte Objekt über eine nicht sichtbare serialVersionUID, die es Ad Hoc erstellt und merkt, dass sich die ehemalige Klasse von der neueren unterscheidet. Aber somit wäre es ja nicht möglich, eine Klasse weiterzuentwickeln, wenn man sich auf eine bestimmte Version der Klasse festlegen muss. Aber wenn die serialVersionUID gesetzt ist, vergleicht Java nur noch diese Nummer. Und wenn sie identisch ist, versucht Java das Objekt der neuern Klasse zuzuordnen, auch wenn sich die neuere Klasse von der älteren unterscheidet. Und wenn das alte Objekt also keine Objekt Variable mit dem Namen der Katze erhält, dann wird der Name der Katze einfach auf null gesetzt. Um Ihnen das vorzuführen, entferne ich die Objekt Variable für den Namen der Katze wieder und auch die Getter und Setter natürlich. Und dann lasse ich mir von Eclipse helfen, in dem ich mit der Maus wieder über den Klassenbezeichner wandere. Und im auftauchenden Kontextmenü habe ich nun folgende Auswahl. Entweder ich lasse mir eine Default Serial Version ID erzeugen oder ich lasse mir eine Generate Serial Version ID erstellen oder meiner Klasse wird die Annotation @SuppressWarnings beigefügt oder ja bei Eclipse wird mir die Konfiguration umgestellt, aber das wollen wir ja nicht. Und mit der dritten Option wird die Warnung ja auch bloß unterdrückt. Auch das ist jetzt keine Lösung. Und bei der ersten Option wird als Serial Version UID eine null gesetzt. Diese Option würde ich verwenden, wenn ich sichergehen will, dass die Zuordnung der gespeicherten Objekte, immer versucht werden soll. Auch wenn sich die Inhalte der Klasse unterscheiden. Diese wähle ich jetzt aber nicht. Aber mit der zweiten Option wird mir eine Serial Version UID erzeugt, die eindeutig ist. Diese Option wähle ich. In diesem Video haben die Voraussetzung gelernt, die eine Klasse mitbringen muss, damit ein hieraus erzeugtes Objekt in einen Datenstrom geschrieben werden kann. Und zwar ist es das Interface Serializable, das die Klasse implementieren muss, damit Ihr Objekt serialisierbar ist. Außerdem habe ich Ihnen erklärt, dass eine serialisierbare Klasse eine Serial Version UID enthalten muss, damit das hieraus erzeugte Objekt versionsübergreifend einlesbar ist.

Java Grundkurs 3: Generische Programmierung, Datenströme, Datumsrechnung

Steigen Sie tiefer in die Java-Programierung ein und lernen Sie den Umgang mit generischen Typen, Lamda-Ausdrücken, DAtenströmen und mit Datums- und Zeitberechnung.

5 Std. 24 min (47 Videos)
Derzeit sind keine Feedbacks vorhanden...
Hersteller:
Software:
Exklusiv für Abo-Kunden
Erscheinungsdatum:09.10.2016

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!