diff options
Diffstat (limited to 'Master/Reference Architectures and Patterns/hjp5/html/k100262.html')
| -rw-r--r-- | Master/Reference Architectures and Patterns/hjp5/html/k100262.html | 581 |
1 files changed, 581 insertions, 0 deletions
diff --git a/Master/Reference Architectures and Patterns/hjp5/html/k100262.html b/Master/Reference Architectures and Patterns/hjp5/html/k100262.html new file mode 100644 index 0000000..1714621 --- /dev/null +++ b/Master/Reference Architectures and Patterns/hjp5/html/k100262.html @@ -0,0 +1,581 @@ +<html>
+<head>
+<title>
+Handbuch der Java-Programmierung, 5. Auflage
+</title>
+</head>
+<body>
+<a name="startofbody"></a>
+<script language="JavaScript" src="hjp4lib.js">
+</script>
+<script language="JavaScript">
+installKbdHandler("97,#startofbody;101,#endofbody;116,cover.html;122,k100003.html;115,search.html;105,index.html;100,JDKDOCS;112,APIDOCS;104,k100260.html;106,k100261.html;107,k100263.html;108,k100265.html");
+</script>
+<table border=0 cellpadding=0 cellspacing=1 width="100%">
+<tr bgcolor="#EEFFCC">
+<td width="7%" align=center bgcolor="#DDCC99"><a href="cover.html"> Titel </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100003.html"> Inhalt </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="search.html"> Suchen </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="index.html"> Index </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/index.html" onClick="this.href=getDocIndex()"> DOC </a>
+<td align="right">Handbuch der Java-Programmierung, 5. Auflage
+<tr bgcolor="#EEFFCC">
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100260.html"> << </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100261.html"> < </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100263.html"> > </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100265.html"> >> </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/api/index.html" onClick="this.href=getApiIndex()"> API </a>
+<td align="right">Kapitel 41 - Serialisierung
+</table>
+<hr>
+
+
+<!-- Section -->
+<a name="sectlevel2id041002"></a>
+<h2>41.2 Weitere Aspekte der Serialisierung </h2>
+<hr>
+<ul>
+<li><a href="k100262.html#sectlevel2id041002">41.2 Weitere Aspekte der Serialisierung</a>
+<ul>
+<li><a href="k100262.html#versionierung">41.2.1 Versionierung</a>
+<li><a href="k100262.html#sectlevel3id041002002">41.2.2 Nicht-serialisierte Membervariablen</a>
+<li><a href="k100262.html#objektreferenzen">41.2.3 Objektreferenzen</a>
+<li><a href="k100262.html#sectlevel3id041002004">41.2.4 Serialisieren von Collections</a>
+</ul>
+</ul>
+<hr>
+
+<p>
+Mit den Grundlagen aus dem vorigen Abschnitt sind bereits die wichtigsten
+Prinzipien der Serialisierung in Java erklärt. Beeindruckend
+ist dabei einerseits, wie das Konzept in die Klassenbibliothek eingebunden
+wurde. <a href="index_o.html#ixb101007"><font color=#000080><tt>ObjectOutputStream</tt></font></a>
+und <a href="index_o.html#ixb101038"><font color=#000080><tt>ObjectInputStream</tt></font></a>
+passen in natürlicher Weise in die Stream-Hierarchie und zeigen,
+wie man Streams konstruiert, die <i>strukturierte</i> Daten verarbeiten.
+Andererseits ist es eine große Hilfe, dass Objekte ohne größere
+Änderungen serialisiert werden können. Es ist lediglich
+erforderlich, das <a href="index_s.html#ixb100454"><font color=#000080><tt>Serializable</tt></font></a>-Interface
+zu implementieren, um ein einfaches Objekt persistent machen zu können.
+
+<p>
+Dennoch ist das API leistungsfähig genug, auch komplexe Klassen
+serialisierbar zu machen. Wir wollen in diesem Abschnitt weiterführende
+Aspekte betrachten, die im Rahmen dieser Einführung noch verständlich
+sind. Daneben gibt es weitere Möglichkeiten, mit denen das Serialisieren
+und Deserialisieren von Klassen komplett an die speziellen Anforderungen
+einer Applikation angepasst werden kann. Auf diese Details wollen
+wir hier aber nicht eingehen. Als vertiefende Lektüre empfiehlt
+sich die »Java Object Serialization Specification«, die
+seit der Version 1.2 Bestandteil der Online-Dokumentation des JDK
+ist.
+
+<!-- Section -->
+
+<a name="versionierung"></a>
+<h3>41.2.1 Versionierung </h3>
+
+<p>
+Applikationen, in denen Code und Daten getrennt gehalten werden, haben
+grundsätzlich mit dem Problem der Inkonsistenz beider Bestandteile
+zu kämpfen. Wie kann sichergestellt werden, dass die Struktur
+der zu verarbeitenden Daten tatsächlich den vom Programm erwarteten
+Strukturen entspricht? Dieses Problem gibt es bei praktisch allen
+Datenbankanwendungen, und es tritt immer dann verstärkt auf,
+wenn Code und Datenstruktur getrennt geändert werden. Auch durch
+das Serialisieren von Objekten haben wir das Problem, denn die Datei
+mit den serialisierten Objekten enthält nur die <i>Daten</i>,
+der zugehörige <i>Code</i> kommt dagegen aus dem <font color="#660099">.class</font>-File.
+
+<p>
+Das Serialisierungs-API versucht diesem Problem mit einem <a name="ixa103018"><i>Versionierungsmechanismus</i></a>
+zu begegnen. Dazu enthält das Interface <a href="index_s.html#ixb100454"><font color=#000080><tt>Serializable</tt></font></a>
+eine <a href="index_l.html#ixb100245"><font color=#000080><tt>long</tt></font></a>-Konstante
+<a name="ixa103019"><a href="index_s.html#ixb102217"><font color=#000080><tt>serialVersionUID</tt></font></a></a>,
+in der eine Versionskennung zur Klasse gespeichert wird. Sie wird
+beim Aufruf von <a href="index_w.html#ixb102213"><font color=#000080><tt>writeObject</tt></font></a>
+automatisch berechnet und stellt einen Hashcode über die wichtigsten
+Eigenschaften der Klasse dar. So gehen beispielsweise Name und Signatur
+der Klasse, implementierte Interfaces sowie Methoden und Konstruktoren
+in die Berechnung ein. Selbst triviale Änderungen wie das Umbenennen
+oder Hinzufügen einer öffentlichen Methode verändern
+die <a href="index_s.html#ixb102217"><font color=#000080><tt>serialVersionUID</tt></font></a>.
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#0099CC"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=1></td>
+<td width=1 align=left valign=top bgcolor="#0099CC"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Die <a href="index_s.html#ixb102217"><font color=#000080><tt>serialVersionUID</tt></font></a>
+einer Klasse kann mit Hilfe des Hilfsprogramms <a name="ixa103020"><a href="index_s.html#ixb102218"><font color=#000080><tt>serialver</tt></font></a></a>
+ermittelt werden. Dieses einfache Programm wird zusammen mit dem Namen
+der Klasse in der Kommandozeile aufgerufen und liefert die Versionsnummer
+als Ausgabe. Alternativ kann es auch mit dem Argument <font color="#000077"><tt>-show</tt></font>
+aufgerufen werden. Es hat dann eine einfache Oberfläche, in der
+der Name der Klasse interaktiv eingegeben werden kann (siehe <a href="k100262.html#serialver">Abbildung 41.1</a>).</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#0099CC">
+<tr>
+<td><font color="#FFFFFF"> Tipp </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#0099CC"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+<p>
+<a name="serialver"></a>
+<img src="images/SerialVer.gif">
+<p>
+
+<p><i>
+Abbildung 41.1: Das Programm serialver</i></p>
+
+<p>
+Beim Serialisieren eines Objektes wird auch die <a href="index_s.html#ixb102217"><font color=#000080><tt>serialVersionUID</tt></font></a>
+der zugehörigen Klasse mit in die Ausgabedatei geschrieben. Soll
+das Objekt später deserialisiert werden, so wird die in der Datei
+gespeicherte <a href="index_s.html#ixb102217"><font color=#000080><tt>serialVersionUID</tt></font></a>
+mit der aktuellen <a href="index_s.html#ixb102217"><font color=#000080><tt>serialVersionUID</tt></font></a>
+des geladenen <font color="#660099">.class</font>-Files verglichen.
+Stimmen beide nicht überein, so gibt es eine Ausnahme des Typs
+<a name="ixa103021"><a href="index_i.html#ixb102219"><font color=#000080><tt>InvalidClassException</tt></font></a></a>,
+und der Deserialisierungsvorgang bricht ab.
+
+<p>
+Diese Art der Versionierung ist zwar recht sicher, aber auch sehr
+rigoros. Schon eine kleine Änderung an der Klasse macht die serialisierten
+Objekte unbrauchbar, weil sie sich nicht mehr deserialisieren lassen.
+Die in <a href="k100261.html#timelisting">Listing 41.1</a> vorgestellte
+Klasse <font color="#000077"><tt>Time</tt></font> hat die <a href="index_s.html#ixb102217"><font color=#000080><tt>serialVersionUID</tt></font></a>
+<font color="#000077"><tt>-8717671986526504937L</tt></font>. Wird
+beispielsweise eine neue Methode <font color="#000077"><tt>public
+void test()</tt></font> hinzugefügt (die für das Deserialisieren
+eigentlich völlig bedeutungslos ist), ändert sich die <a href="index_s.html#ixb102217"><font color=#000080><tt>serialVersionUID</tt></font></a>
+auf <font color="#000077"><tt>9202005869290334574L</tt></font>, und
+weder die Datei <font color="#660099">test1.ser</font> noch <font color="#660099">test2.ser</font>
+lassen sich zukünftig deserialisieren.
+
+<p>
+Anstatt die <a href="index_s.html#ixb102217"><font color=#000080><tt>serialVersionUID</tt></font></a>
+automatisch berechnen zu lassen, kann sie von der zu serialisierenden
+Klasse auch fest vorgegeben werden. Dazu wird einfach eine Konstante
+<font color="#000077"><tt>static final long serialVersionUID</tt></font>
+definiert und mit einem vorgegebenen Wert belegt (der zum Beispiel
+mit Hilfe von <a href="index_s.html#ixb102218"><font color=#000080><tt>serialver</tt></font></a>
+ermittelt wird). In diesem Fall wird die <a href="index_s.html#ixb102217"><font color=#000080><tt>serialVersionUID</tt></font></a>
+beim Aufruf von <a href="index_w.html#ixb102213"><font color=#000080><tt>writeObject</tt></font></a>
+nicht neu berechnet, sondern es wird der vorgegebene Wert verwendet.
+Läßt man diese Konstante unverändert, können
+beliebige Änderungen der Klasse durchgeführt werden, ohne
+dass <a href="index_r.html#ixb102215"><font color=#000080><tt>readObject</tt></font></a>
+beim Deserialisieren mit einer Ausnahme abbricht. Die <font color="#000077"><tt>Time</tt></font>-Klasse
+aus <a href="k100261.html#timelisting">Listing 41.1</a> hätte
+dann folgendes Aussehen:
+<a name="listingid041006"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#0000AA">import</font> java.io.*;
+<font color="#555555">002 </font>
+<font color="#555555">003 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Time
+<font color="#555555">004 </font><font color="#0000AA">implements</font> Serializable
+<font color="#555555">005 </font>{
+<font color="#555555">006 </font> <font color="#0000AA">static</font> <font color="#0000AA">final</font> <font color="#006699">long</font> serialVersionUID = -8717671986526504937L;
+<font color="#555555">007 </font>
+<font color="#555555">008 </font> <font color="#0000AA">private</font> <font color="#006699">int</font> hour;
+<font color="#555555">009 </font> <font color="#0000AA">private</font> <font color="#006699">int</font> minute;
+<font color="#555555">010 </font>
+<font color="#555555">011 </font> <font color="#0000AA">public</font> Time(<font color="#006699">int</font> hour, <font color="#006699">int</font> minute)
+<font color="#555555">012 </font> {
+<font color="#555555">013 </font> <font color="#006699">this</font>.hour = hour;
+<font color="#555555">014 </font> <font color="#006699">this</font>.minute = minute;
+<font color="#555555">015 </font> }
+<font color="#555555">016 </font>
+<font color="#555555">017 </font> <font color="#0000AA">public</font> String toString()
+<font color="#555555">018 </font> {
+<font color="#555555">019 </font> <font color="#0000AA">return</font> hour + <font color="#0000FF">":"</font> + minute;
+<font color="#555555">020 </font> }
+<font color="#555555">021 </font>}</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 41.6: Die Uhrzeitklasse mit serialVersionUID</i></p>
+
+<p>
+Jetzt muss die Anwendung natürlich selbst darauf achten, dass
+die durchgeführten Änderungen kompatibel sind, dass also
+durch das Laden der Daten aus dem älteren Objekt keine Inkonsistenzen
+verursacht werden. Dabei mögen folgende Regeln als Anhaltspunkte
+dienen:
+<ul>
+<li>Das Hinzufügen oder Entfernen von Methoden ist meist unkritisch.
+<li>Das Entfernen von Membervariablen ist meist unkritisch.
+<li>Beim Hinzufügen neuer Membervariablen muss beachtet werden,
+dass diese nach dem Deserialisieren uninitialisiert sind.
+<li>Problematisch ist es meist, Membervariablen umzubenennen, sie
+auf <a href="index_t.html#ixb100429"><font color=#000080><tt>transient</tt></font></a>
+oder <a href="index_s.html#ixb100422"><font color=#000080><tt>static</tt></font></a>
+(oder umgekehrt) zu ändern, die Klasse von <a href="index_s.html#ixb100454"><font color=#000080><tt>Serializable</tt></font></a>
+auf <a name="ixa103022"><a href="index_e.html#ixb102220"><font color=#000080><tt>Externalizable</tt></font></a></a>
+(oder umgekehrt) zu ändern oder den Klassennamen zu ändern.
+</ul>
+
+<p>
+Solange die Änderungen kompatibel bleiben, ist also durch eine
+feste <a href="index_s.html#ixb102217"><font color=#000080><tt>serialVersionUID</tt></font></a>
+sichergestellt, dass serialisierte Objekte lesbar und deserialisierbar
+bleiben. Sind die Änderungen dagegen inkompatibel, sollte die
+Konstante entsprechend geändert werden, und die serialisierten
+Daten dürfen nicht mehr verwendet werden (bzw. müssen vor
+der weiteren Verwendung konvertiert werden).
+
+<!-- Section -->
+
+<a name="sectlevel3id041002002"></a>
+<h3>41.2.2 Nicht-serialisierte Membervariablen </h3>
+
+<p>
+Mitunter besitzt eine Klasse Membervariablen, die nicht serialisiert
+werden sollen. Typische Beispiele sind Variablen, deren Wert sich
+während des Programmlaufs dynamisch ergibt, oder solche, die
+nur der temporären Kommunikation zwischen zwei oder mehr Methoden
+dienen. Auch Daten, die nur im Kontext der laufenden Anwendung Sinn
+machen, wie beispielsweise Filehandles, Sockets, GUI-Ressourcen oder
+JDBC-Verbindungen, sollten nicht serialisiert werden; sie »verfallen«
+mit dem Ende des Programms.
+
+<p>
+Membervariablen, die nicht serialisiert werden sollen, können
+mit dem Attribut <a name="ixa103023"><a href="index_t.html#ixb100429"><font color=#000080><tt>transient</tt></font></a></a>
+versehen werden. Dadurch werden sie beim Schreiben des Objekts mit
+<a href="index_w.html#ixb102213"><font color=#000080><tt>writeObject</tt></font></a>
+ignoriert und gelangen nicht in die Ausgabedatei. Beim Deserialisieren
+werden die transienten Objekte lediglich mit dem typspezifischen Standardwert
+belegt.
+
+<!-- Section -->
+
+<a name="objektreferenzen"></a>
+<h3>41.2.3 Objektreferenzen </h3>
+
+<p>
+Eine wichtige Eigenschaft des Serialisierungs-APIs im JDK ist die,
+dass auch <i>Referenzen</i> automatisch gesichert und rekonstruiert
+werden. Besitzt ein Objekt selbst Strings, Arrays oder andere Objekte
+als Membervariablen, so werden diese ebenso wie die primitiven Typen
+serialisiert und deserialisiert. Da eine Objektvariable lediglich
+einen <i>Verweis</i> auf das im Hauptspeicher allozierte Objekt darstellt,
+ist es wichtig, dass diese Verweise auch nach dem Serialisieren/Deserialisieren
+erhalten bleiben. Insbesondere darf ein Objekt auch dann nur einmal
+angelegt werden, wenn darauf von mehr als einer Variable verwiesen
+wird. Auch nach dem Deserialisieren darf das Objekt nur einmal vorhanden
+sein, und die verschiedenen Objektvariablen müssen auf dieses
+Objekt zeigen.
+
+<p>
+Der <a href="index_o.html#ixb101007"><font color=#000080><tt>ObjectOutputStream</tt></font></a>
+hält zu diesem Zweck eine Hashtabelle, in der alle bereits serialisierten
+Objekte verzeichnet werden. Bei jedem Aufruf von <a href="index_w.html#ixb102213"><font color=#000080><tt>writeObject</tt></font></a>
+wird zunächst in der Tabelle nachgesehen, ob das Objekt bereits
+serialisiert wurde. Ist das der Fall, wird in der Ausgabedatei lediglich
+ein Verweis auf das Objekt gespeichert. Andernfalls wird das Objekt
+serialisiert und in der Hashtabelle eingetragen. Beim Deserialisieren
+eines Verweises wird dieser durch einen Objektverweis auf das zuvor
+deserialisierte Objekt ersetzt. Auf diese Weise werden Objekte nur
+einmal gespeichert, die Objektreferenzen werden konserviert, und das
+Problem von Endlosschleifen durch zyklische Referenzen ist ebenfalls
+gelöst.
+
+<p>
+Das folgende Programm zeigt das Speichern von Verweisen am Beispiel
+eines Graphen, der Eltern-Kind-Beziehungen darstellt. Zunächst
+benötigen wir dazu eine Klasse <font color="#000077"><tt>Person</tt></font>,
+die den Namen und die Eltern einer Person speichern kann. Jeder Elternteil
+wird dabei durch einen Verweis auf eine weitere Person dargestellt:
+<a name="listingid041007"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#0000AA">import</font> java.io.*;
+<font color="#555555">002 </font>
+<font color="#555555">003 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Person
+<font color="#555555">004 </font><font color="#0000AA">implements</font> Serializable
+<font color="#555555">005 </font>{
+<font color="#555555">006 </font> <font color="#0000AA">public</font> String name;
+<font color="#555555">007 </font> <font color="#0000AA">public</font> Person mother;
+<font color="#555555">008 </font> <font color="#0000AA">public</font> Person father;
+<font color="#555555">009 </font>
+<font color="#555555">010 </font> <font color="#0000AA">public</font> Person(String name)
+<font color="#555555">011 </font> {
+<font color="#555555">012 </font> <font color="#006699">this</font>.name = name;
+<font color="#555555">013 </font> }
+<font color="#555555">014 </font>}</pre>
+</font>
+</td>
+<td valign=top align=right>
+<a href="../examples/Person.java"><font color="#000055" size=-1>Person.java</font></a></td>
+</tr>
+</table>
+<i>
+Listing 41.7: Die Klasse Person</i></p>
+
+<p>
+Der Einfachheit halber wurden alle Membervariablen als <a href="index_p.html#ixb100084"><font color=#000080><tt>public</tt></font></a>
+deklariert. Wir wollen nun ein Programm erstellen, das den folgenden
+Eltern-Kind-Graph aufbaut:
+<p>
+<a name="elternkindgraph"></a>
+<img src="images/ElternKindSeri.gif">
+<p>
+
+<p><i>
+Abbildung 41.2: Eltern-Kind-Graph für Serialisierungsbeispiel</i></p>
+
+<p>
+Das Programm soll den Graph dann in eine Datei <font color="#660099">test3.ser</font>
+serialisieren und anschließend durch Deserialisieren wieder
+rekonstruieren. Wir wollen dann überprüfen, ob alle Verweise
+wiederhergestellt wurden und ob die Objekteindeutigkeit gewahrt wurde.
+<a name="seriref"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#00AA00">/* Listing4108.java */</font>
+<font color="#555555">002 </font>
+<font color="#555555">003 </font><font color="#0000AA">import</font> java.io.*;
+<font color="#555555">004 </font><font color="#0000AA">import</font> java.util.*;
+<font color="#555555">005 </font>
+<font color="#555555">006 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Listing4108
+<font color="#555555">007 </font>{
+<font color="#555555">008 </font> <font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> main(String[] args)
+<font color="#555555">009 </font> {
+<font color="#555555">010 </font> <font color="#00AA00">//Erzeugen der Familie</font>
+<font color="#555555">011 </font> Person opa = <font color="#0000AA">new</font> Person(<font color="#0000FF">"Eugen"</font>); <a name="seriref.a"></a>
+<font color="#555555">012 </font> Person oma = <font color="#0000AA">new</font> Person(<font color="#0000FF">"Therese"</font>);
+<font color="#555555">013 </font> Person vater = <font color="#0000AA">new</font> Person(<font color="#0000FF">"Barny"</font>);
+<font color="#555555">014 </font> Person mutter = <font color="#0000AA">new</font> Person(<font color="#0000FF">"Wilma"</font>);
+<font color="#555555">015 </font> Person kind1 = <font color="#0000AA">new</font> Person(<font color="#0000FF">"Fritzchen"</font>);
+<font color="#555555">016 </font> Person kind2 = <font color="#0000AA">new</font> Person(<font color="#0000FF">"Kalli"</font>);
+<font color="#555555">017 </font> vater.father = opa;
+<font color="#555555">018 </font> vater.mother = oma;
+<font color="#555555">019 </font> kind1.father = kind2.father = vater;
+<font color="#555555">020 </font> kind1.mother = kind2.mother = mutter; <a name="seriref.b"></a>
+<font color="#555555">021 </font>
+<font color="#555555">022 </font> <font color="#00AA00">//Serialisieren der Familie</font>
+<font color="#555555">023 </font> <font color="#0000AA">try</font> {
+<font color="#555555">024 </font> FileOutputStream fs = <font color="#0000AA">new</font> FileOutputStream(<font color="#0000FF">"test3.ser"</font>);
+<font color="#555555">025 </font> ObjectOutputStream os = <font color="#0000AA">new</font> ObjectOutputStream(fs);
+<font color="#555555">026 </font> os.writeObject(kind1);
+<font color="#555555">027 </font> os.writeObject(kind2);
+<font color="#555555">028 </font> os.close();
+<font color="#555555">029 </font> } <font color="#0000AA">catch</font> (IOException e) {
+<font color="#555555">030 </font> System.err.println(e.toString());
+<font color="#555555">031 </font> }
+<font color="#555555">032 </font>
+<font color="#555555">033 </font> <font color="#00AA00">//Rekonstruieren der Familie</font>
+<font color="#555555">034 </font> kind1 = kind2 = <font color="#006699">null</font>; <a name="seriref.c"></a>
+<font color="#555555">035 </font> <font color="#0000AA">try</font> {
+<font color="#555555">036 </font> FileInputStream fs = <font color="#0000AA">new</font> FileInputStream(<font color="#0000FF">"test3.ser"</font>);
+<font color="#555555">037 </font> ObjectInputStream is = <font color="#0000AA">new</font> ObjectInputStream(fs);
+<font color="#555555">038 </font> kind1 = (Person)is.readObject();
+<font color="#555555">039 </font> kind2 = (Person)is.readObject();
+<font color="#555555">040 </font> <font color="#00AA00">//Überprüfen der Objekte</font>
+<font color="#555555">041 </font> System.out.println(kind1.name); <a name="seriref.d"></a>
+<font color="#555555">042 </font> System.out.println(kind2.name);
+<font color="#555555">043 </font> System.out.println(kind1.father.name);
+<font color="#555555">044 </font> System.out.println(kind1.mother.name);
+<font color="#555555">045 </font> System.out.println(kind2.father.name);
+<font color="#555555">046 </font> System.out.println(kind2.mother.name);
+<font color="#555555">047 </font> System.out.println(kind1.father.father.name);
+<font color="#555555">048 </font> System.out.println(kind1.father.mother.name); <a name="seriref.e"></a>
+<font color="#555555">049 </font> <font color="#00AA00">//Name des Vaters ändern</font>
+<font color="#555555">050 </font> kind1.father.name = <font color="#0000FF">"Fred"</font>; <a name="seriref.f"></a>
+<font color="#555555">051 </font> <font color="#00AA00">//Erneutes Überprüfen der Objekte</font>
+<font color="#555555">052 </font> System.out.println(<font color="#0000FF">"---"</font>); <a name="seriref.g"></a>
+<font color="#555555">053 </font> System.out.println(kind1.name);
+<font color="#555555">054 </font> System.out.println(kind2.name);
+<font color="#555555">055 </font> System.out.println(kind1.father.name);
+<font color="#555555">056 </font> System.out.println(kind1.mother.name);
+<font color="#555555">057 </font> System.out.println(kind2.father.name);
+<font color="#555555">058 </font> System.out.println(kind2.mother.name);
+<font color="#555555">059 </font> System.out.println(kind1.father.father.name);
+<font color="#555555">060 </font> System.out.println(kind1.father.mother.name); <a name="seriref.h"></a>
+<font color="#555555">061 </font> is.close();
+<font color="#555555">062 </font> } <font color="#0000AA">catch</font> (ClassNotFoundException e) {
+<font color="#555555">063 </font> System.err.println(e.toString());
+<font color="#555555">064 </font> } <font color="#0000AA">catch</font> (IOException e) {
+<font color="#555555">065 </font> System.err.println(e.toString());
+<font color="#555555">066 </font> }
+<font color="#555555">067 </font> }
+<font color="#555555">068 </font>}</pre>
+</font>
+</td>
+<td valign=top align=right>
+<a href="../examples/Listing4108.java"><font color="#000055" size=-1>Listing4108.java</font></a></td>
+</tr>
+</table>
+<i>
+Listing 41.8: Serialisieren von Objekten und Referenzen</i></p>
+
+<p>
+Das Programm erzeugt in den Zeilen <a href="k100262.html#seriref.a">011</a>
+bis <a href="k100262.html#seriref.b">020</a> zunächst den in
+<a href="k100262.html#elternkindgraph">Abbildung 41.2</a> abgebildeten
+Verwandtschaftsgraph und serialisiert ihn anschließend in die
+Datei <font color="#660099">test3.ser</font>. Bemerkenswert ist hier
+vor allem, dass wir lediglich die beiden Kinder <font color="#000077"><tt>kind1</tt></font>
+und <font color="#000077"><tt>kind2</tt></font> explizit serialisieren.
+Da alle anderen Objekte über Verweise von den Kindern aus zu
+erreichen sind, ist es nicht nötig, diese separat mit <a href="index_w.html#ixb102213"><font color=#000080><tt>writeObject</tt></font></a>
+zu speichern.
+
+<p>
+In <a href="k100262.html#seriref.c">Zeile 034</a> setzen wir die beiden
+Kindvariablen auf <a href="index_n.html#ixb100235"><font color=#000080><tt>null</tt></font></a>,
+um zu beweisen, dass sie ausschließlich durch das nachfolgende
+Deserialisieren korrekt gesetzt werden. Nun werden <font color="#000077"><tt>kind1</tt></font>
+und <font color="#000077"><tt>kind2</tt></font> deserialisiert, und
+in den Zeilen <a href="k100262.html#seriref.d">041</a> bis <a href="k100262.html#seriref.e">048</a>
+wird der komplette Verwandtschaftsgraph ausgegeben. An der Ausgabe
+des Programms können wir erkennen, dass tatsächlich alle
+Objekte rekonstruiert und die Verweise darauf korrekt gesetzt wurden:
+<font color="#333300">
+<pre>
+Fritzchen
+Kalli
+Barny
+Wilma
+Barny
+Wilma
+Eugen
+Therese
+---
+Fritzchen
+Kalli
+Fred
+Wilma
+Fred
+Wilma
+Eugen
+Therese
+</pre>
+</font>
+
+<p>
+Der zweite Block von Ausgabeanweisungen (in den Zeilen <a href="k100262.html#seriref.g">052</a>
+bis <a href="k100262.html#seriref.h">060</a>) zeigt, dass auch die
+Objekteindeutigkeit gewahrt wurde. Dazu haben wir nämlich in
+<a href="k100262.html#seriref.f">Zeile 050</a> den Namen des Vaterobjekts
+von <font color="#000077"><tt>kind1</tt></font> auf »Fred«
+geändert. Wie im zweiten Teil der Ausgabe des Programms zu erkennen
+ist, wurde damit auch der Name des Vaters des zweiten Kindes auf »Fred«
+geändert, und wir können sicher sein, dass es sich um ein
+und dasselbe Objekt handelt.
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=1></td>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Obwohl (oder gerade weil) das Serialisieren von Objektgraphen in aller
+Regel sehr bequem und vollautomatisch abläuft, seien an dieser
+Stelle einige Warnungen ausgesprochen:
+<ul>
+<li>Einerseits kann es passieren, dass mehr Objekte als erwartet serialisiert
+werden. Insbesondere bei komplexen Objektbeziehungen kann es sein,
+dass an dem zu serialisierenden Objekt indirekt viele weitere Objekte
+hängen und beim Serialisieren wesentlich mehr Objekte gespeichert
+werden, als erwartet wurde. Das kostet unnötig Zeit und Speicher.
+<li>Durch das Zwischenspeichern der bereits serialisierten Objekte
+in <a href="index_o.html#ixb101007"><font color=#000080><tt>ObjectOutputStream</tt></font></a>
+werden viele Verweise auf Objekte gehalten, die sonst möglicherweise
+für das Programm unerreichbar wären. Da der Garbage Collector
+diese Objekte nicht freigibt, kann es beim Serialisieren einer großen
+Anzahl von Objekten zu Speicherproblemen kommen. Mit Hilfe der Methode
+<a name="ixa103024"><a href="index_r.html#ixb100977"><font color=#000080><tt>reset</tt></font></a></a>
+kann der <a href="index_o.html#ixb101007"><font color=#000080><tt>ObjectOutputStream</tt></font></a>
+in den Anfangszustand versetzt werden; alle bereits bekannten Objektreferenzen
+werden »vergessen«. Wird ein bereits serialisiertes Objekt
+danach noch einmal gespeichert, wird kein Verweis, sondern das Objekt
+selbst noch einmal geschrieben.
+<li>Wenn ein bereits serialisiertes Objekt <i>verändert</i> und
+anschließend erneut serialisiert wird, bleibt die Veränderung
+beim Deserialisieren unsichtbar, denn in der Ausgabedatei wird lediglich
+ein Verweis auf das Originalobjekt gespeichert.
+</ul>
+</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#CC0000">
+<tr>
+<td><font color="#FFFFFF"> Warnung </font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+
+<!-- Section -->
+<a name="sectlevel3id041002004"></a>
+<h3>41.2.4 Serialisieren von Collections </h3>
+
+<p>
+Neben selbstgeschriebenen Klassen sind auch viele der Standardklassen
+des JDK serialisierbar, insbesondere die meisten Collection-Klassen.
+Um beispielsweise alle Daten eines Vektors oder einer Hashtable persistent
+zu speichern, genügt ein einfaches Serialisieren nach obigem
+Muster. Voraussetzung ist allerdings, dass auch die Elemente der Collection
+serialisierbar sind, andernfalls gibt es eine <a name="ixa103025"><a href="index_n.html#ixb102214"><font color=#000080><tt>NotSerializableException</tt></font></a></a>.
+Auch die Wrapperklassen zu den Basistypen (siehe <a href="k100066.html#wrapperklassen">Abschnitt 10.2</a>)
+sind standardmäßig serialisierbar und können damit
+problemlos als Objekte in serialisierbaren Collections verwendet werden.
+Im nächsten Abschnitt stellen wir eine kleine Anwendung für
+das Serialisieren von Hashtabellen vor.
+<hr>
+<table border=0 cellpadding=0 cellspacing=1 width="100%">
+<tr bgcolor="#EEFFCC">
+<td width="7%" align=center bgcolor="#DDCC99"><a href="cover.html"> Titel </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100003.html"> Inhalt </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="search.html"> Suchen </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="index.html"> Index </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/index.html" onClick="this.href=getDocIndex()"> DOC </a>
+<td align="right">Handbuch der Java-Programmierung, 5. Auflage, Addison
+Wesley, Version 5.0.1
+<tr bgcolor="#EEFFCC">
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100260.html"> << </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100261.html"> < </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100263.html"> > </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100265.html"> >> </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/api/index.html" onClick="this.href=getApiIndex()"> API </a>
+<td align="right">© 1998, 2007 Guido Krüger & Thomas
+Stark, <a href="http://www.javabuch.de">http://www.javabuch.de</a>
+</table>
+<a name="endofbody"></a>
+</body>
+</html>
|
