11.1.1 Beispiele Schnittstellenanwendung

 Serialisierung

Serialisierung ist ein Beispiel bei dem man gut sieht wie eine Klasse durch Implementierung einer Schnittstelle wichtige Eigenschaften gewinnen man. Man kann sie in einer Datei speichern oder in einen beliebigen Stream stecken!

Java bietet die Möglichkeit Objekte im Hauptspeicher in einen seriellen Datenstron zu konvertieren den man zum Beispiel in Dateien schreiben kann. Diese Technologie nennt man Serialisierung(engl. Serialization siehe Wikipedia). Java kann Klassen serialisieren die die Schnittstelle Serializable implementieren.

Java kann Objekte serialisieren wenn

  • die entsprechende Klasse die Schnittstelle Serializable implementiert und
  • wenn alle Attribute die auf Objekte zeigen auch die Schnittstelle Serializable implementieren

Das folgende Beispielprogramm ist in der Lage eine Person und ihre Adresse in eine Datei zu schreiben und wieder zu lesen.

Alles was man tun muss um die Klassen Person und Adresse serialisierbar zu machen ist die Schlüsselworte "implements Serializable" hinzuzufügen

 Heap Diagramm mit vier Objekten zur Serialisierung
  1. Im Hauptprogramm wird eine Person Urmel angelegt die auf eine Adresse Lummerland zeigt
  2. Die Methode Methode schreiben() schreibt alle von p referenzierten Objekte in eine Datei serialisiert.ser
  3. Die Methode lesen() liest die Person und alle referenzierten Objekte aus der Datei zurück
  4. p1 zeigt nun auf eine neue Person mit eigenen referenzierten Objekt Adresse

 

 Überlegungen:

  • Die Schnittstelle Serializable fordert keine Methoden zu implementieren!
  • Warum sind 4 Objekte in der Datei?
  • Was würde geschehen wenn die die Klasse Person mit Stammbaum aus der ersten Vorlesung serialisieren würde?
  • Was würde geschehen wenn man weitere Attribute mit Basistypen zu den Klassen hinzufügt?
  • Was geschieht wenn man auf eine Klasse referenziert die nicht serialisierbar ist?

Klasse Serialisierung

package s1.block11;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
*
* @author s@scalingbits.com
*/
public class Serialisierung {
/**
* Erzeuge eine Person und die Adresse. Schreibe sie in eine
* Datei und lese sie aus der Datei
* @param args
*/
   public static void main(String[] args) {
   final String meineDatei = "serialisiert.ser";
   // Erzeuge das Objekt der Person und das Objekt mit der Adresse
   Person p = new Person("Urmel", new Adresse("Lummerland"));
   System.out.println("Zu schreibende Person " + p.name +
      " wohnt in " + p.wohnort.stadt);
   // Schreibe die Objekte in eine Datei
   schreiben(p, meineDatei);
   Person p1 = (Person) lesen(meineDatei);
   System.out.println("Gelesene Person " + p1.name +
      " wohnt in " + p1.wohnort.stadt);
   System.out.println("Die geschrieben Adresse und die gelesene"+
      " Adresse " + p.wohnort.stadt + " sind" +
      (p.wohnort==p1.wohnort? " " : " nicht ") +
      "identisch");
   }
   /**
   * Diese Methode schreibt ein beliebiges serialisierbares Objekt
   * in eine Datei
   * @param o Objekt welches in eine Datei geschrieben wird.
   * Es muss serialisierbar sein!
   * @param datei Die Datei in die geschrieben werden soll
   */
   public static void schreiben(Object o, String datei) {
      try {
         // Erzeuge einen Stream der in eine Datei geleitet wird
         FileOutputStream fileOut = new FileOutputStream(datei);
         // Erzeuge einen Stream der Objekte in einen Filestream leitet
         ObjectOutputStream out = new ObjectOutputStream(fileOut);
         // Schreibe ein beliebiges Objekt in diesen Objectstream
         out.writeObject(o);
        // Schliesse Stream
        out.close();
        // Schliesse Datenstrom. Die letzten Bytes werden so raus geschrieben
          fileOut.close();
        System.out.println("Serialisierte Daten sind gespeichert in Datei "
            + datei);
      } catch (IOException i) { // Hier können Ausnahmen auftreten
         i.printStackTrace();
      }
   }
   /**
   *
   * @param datei die Datei aus der gelesen werden soll
   * @return
   */
   public static Object lesen(String datei) {
      System.out.println("Lesen aus " + datei);
      Object o;
      try { // Hier können Ausnahmen Auftreten
         // Öffne Datei aus der gelesen werden soll
         FileInputStream fileIn = new FileInputStream(datei);
         // Erzeuge Objectstream der aus Datei liest
         ObjectInputStream in = new ObjectInputStream(fileIn);
         //Lies Objekt aus Stream
         o = in.readObject();
         // Schließe Objectstream
         in.close();
         // Schließe Datei
         fileIn.close();
      } catch (IOException i) { // Wird ausgeführt wenn Probleme auftreten
         i.printStackTrace();
         return null;
      } catch (ClassNotFoundException c) {
         System.out.println("Gelesene Klasse nicht gefunden");
         c.printStackTrace();
         return null;
   }
   return o;
   }
}

 

Klasse Adresse

package s1.block11;

import java.io.Serializable;

/**
*
* @author s@scalingbits.com
*/
public class Adresse implements Serializable {
   String stadt;
   public Adresse (String s)
   {
      stadt =s;
   }
}

Klasse Person

package s1.block11;

import java.io.Serializable;

/**
*
* @author s@scalingbits.com
*/
public class Person implements Serializable {
   String name;
   Adresse wohnort;
   public Person(String n, Adresse w) {
      wohnort = w;
      name=n;
   }
}

Weiterführende Übungen und Überlegungen zu diesem Beispiel

  1. Was geschieht wenn zwei Personen auf das gleiche Adressobjekt zeigen? Wird die Adresse zweimal gespeichert oder nur einmal? Selbst wenn die Adresse nur einmal gespeichert wird. Was geschieht beim Lesen der serialisierten Datei. Wird das Addressobjekt verdoppelt?
  2. Was geschieht beim Übersetzen und Ausführen wenn man den Term "implements Serializable" in der Klasse Adresse oder Person weglässt?
  3. Versioning Problem: Was geschieht wenn man die Objekte in eine Datei serialisiert. Dann ein Attribut zu einer Klasse hinzufügt oder weglässt. Dann die serialisierten Objekt wieder einliest?
  4. Was muss man tun wenn man ein Attribut (zBsp. stadt) nicht speichern möchte? Suchen Sie in der Java-Spezifikation oder mit einer Suchmaschine...