Leitfaden für die Externalisierbare Schnittstelle in Java

Anleitung zur externalisierbaren Schnittstelle in Java

1. Einführung

In diesem Tutorial werdenwe’ll have a quick look at java’s java.io.Externalizable interface. Das Hauptziel dieser Schnittstelle besteht darin, eine benutzerdefinierte Serialisierung und Deserialisierung zu ermöglichen.

Bevor wir fortfahren, lesen Sie unbedingt den Artikel vonserialization in Java. Das nächste Kapitel befasst sich mit der Serialisierung eines Java-Objekts mit dieser Schnittstelle.

Danach werden wir die wichtigsten Unterschiede zurjava.io.Serializable-Schnittstelle diskutieren.

2. The Externalizable Schnittstelle

Externalizable erstreckt sich von der Markierungsschnittstelle vonjava.io.Serializable. Any class that implements Externalizable interface should override the writeExternal(), readExternal() methods. Auf diese Weise können wir das Standard-Serialisierungsverhalten der JVM ändern.

2.1. Serialisierung

Schauen wir uns dieses einfache Beispiel an:

public class Country implements Externalizable {

    private static final long serialVersionUID = 1L;

    private String name;
    private int code;

    // getters, setters

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeUTF(name);
        out.writeInt(code);
    }

    @Override
    public void readExternal(ObjectInput in)
      throws IOException, ClassNotFoundException {
        this.name = in.readUTF();
        this.code = in.readInt();
    }
}

Hier haben wir eine KlasseCountrydefiniert, die die SchnittstelleExternalizableimplementiert und die beiden oben genannten Methoden implementiert.

In the writeExternal() method, we’re adding the object’s properties to the ObjectOutput stream. Dies hat Standardmethoden wiewriteUTF() fürString undwriteInt() für die int-Werte.

Als nächstes verwendenfor deserializing the object, we’re reading from the ObjectInput stream die MethodenreadUTF(), readInt(), um die Eigenschaften in derselben genauen Reihenfolge zu lesen, in der sie geschrieben wurden.

Es wird empfohlen, dieserialVersionUID manuell hinzuzufügen. Ist dies nicht der Fall, fügt die JVM automatisch einen hinzu.

Die automatisch generierte Nummer ist vom Compiler abhängig. Dies bedeutet, dass es unwahrscheinlichInvalidClassException verursachen kann.

Testen wir das oben implementierte Verhalten:

@Test
public void whenSerializing_thenUseExternalizable()
  throws IOException, ClassNotFoundException {

    Country c = new Country();
    c.setCode(374);
    c.setName("Armenia");

    FileOutputStream fileOutputStream
     = new FileOutputStream(OUTPUT_FILE);
    ObjectOutputStream objectOutputStream
     = new ObjectOutputStream(fileOutputStream);
    c.writeExternal(objectOutputStream);

    objectOutputStream.flush();
    objectOutputStream.close();
    fileOutputStream.close();

    FileInputStream fileInputStream
     = new FileInputStream(OUTPUT_FILE);
    ObjectInputStream objectInputStream
     = new ObjectInputStream(fileInputStream);

    Country c2 = new Country();
    c2.readExternal(objectInputStream);

    objectInputStream.close();
    fileInputStream.close();

    assertTrue(c2.getCode() == c.getCode());
    assertTrue(c2.getName().equals(c.getName()));
}

In diesem Beispiel erstellen wir zuerst einCountry-Objekt und schreiben es in eine Datei. Anschließend deserialisieren wir das Objekt aus der Datei und überprüfen, ob die Werte korrekt sind.

Die Ausgabe des gedrucktenc2-Objekts:

Country{name='Armenia', code=374}

Dies zeigt, dass wir das Objekt erfolgreich deserialisiert haben.

2.2. Erbe

Wenn eine Klasse von derSerializable-Schnittstelle erbt, sammelt die JVM automatisch auch alle Felder von Unterklassen und macht sie serialisierbar.

Beachten Sie, dass wir dies auch aufExternalizable anwenden können. We just need to implement the read/write methods for every sub-class of the inheritance hierarchy.

Schauen wir uns die KlasseRegionan, die unsere KlasseCountryaus dem vorherigen Abschnitt erweitert:

public class Region extends Country implements Externalizable {

    private static final long serialVersionUID = 1L;

    private String climate;
    private Double population;

    // getters, setters

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        super.writeExternal(out);
        out.writeUTF(climate);
    }

    @Override
    public void readExternal(ObjectInput in)
      throws IOException, ClassNotFoundException {

        super.readExternal(in);
        this.climate = in.readUTF();
    }
}

Hier haben wir zwei zusätzliche Eigenschaften hinzugefügt und die erste serialisiert.

Beachten Sie, dasswe also called super.writeExternal(out), super.readExternal(in) within serializer methods to save/restore the parent class fields as well.

Lassen Sie uns den Komponententest mit den folgenden Daten ausführen:

Region r = new Region();
r.setCode(374);
r.setName("Armenia");
r.setClimate("Mediterranean");
r.setPopulation(120.000);

Hier ist das deserialisierte Objekt:

Region{
  country='Country{
    name='Armenia',
    code=374}'
  climate='Mediterranean',
  population=null
}

Beachten Sie, dasssince we didn’t serialize the population field in Region class, the value of that property is null.

3. Externalizable vsSerializable

Lassen Sie uns die wichtigsten Unterschiede zwischen den beiden Schnittstellen durchgehen:

  • Serialisierungsverantwortung

Der Hauptunterschied besteht darin, wie wir mit dem Serialisierungsprozess umgehen. Wenn eine Klasse diejava.io.Serializable-Schnittstelle implementiert, übernimmt die JVM die volle Verantwortung für die Serialisierung der Klasseninstanz. In case of Externalizable, it’s the programmer who should take care of the whole serialization and also deserialization process.

  • Anwendungsfall

Wenn wir das gesamte Objekt serialisieren müssen, passt dieSerializable-Schnittstelle besser. Andererseitsfor custom serialization, we can control the process using Externalizable.

  • Performance

Diejava.io.Serializable-Schnittstelle verwendet Reflexion und Metadaten, was zu einer relativ langsamen Leistung führt. Zum Vergleich:Externalizable interface gives you full control over the serialization process.

  • Lesereihenfolge

While using Externalizable, it’s mandatory to read all the field states in the exact order as they were written. Andernfalls erhalten wir eine Ausnahme.

Wenn wir beispielsweise die Lesereihenfolge der Eigenschaftencode undname in der KlasseCountry ändern, wird einjava.io.EOFException ausgelöst.

In der Zwischenzeit hat dieSerializable-Schnittstelle diese Anforderung nicht.

  • Benutzerdefinierte Serialisierung

Wir können eine benutzerdefinierte Serialisierung mit derSerializable-Schnittstelle erreichen, indem wir das Feld mit dem Schlüsselworttransient markieren. The JVM won’t serialize the particular field but it’ll add up the field to file storage with the default value. Aus diesem Grund empfiehlt es sich, bei benutzerdefinierten SerialisierungenExternalizable zu verwenden.

4. Fazit

In dieser kurzen Anleitung zurExternalizable-Schnittstelle haben wir die wichtigsten Funktionen, Vorteile und Beispiele für die einfache Verwendung erörtert. Wir haben auch einen Vergleich mit derSerializable-Schnittstelle durchgeführt.

Wie üblich ist der vollständige Quellcode des Tutorialsover on GitHub verfügbar.