Frage

ich habe:

class MyClass extends MyClass2 implements Serializable {
  //...
}

In MyClass2 ist eine Eigenschaft, die nicht serialisierbar ist. Wie kann ich serialisiert (und de-serialize) dieses Objekt?

Korrektur:. MyClass2 ist natürlich nicht eine Schnittstelle, sondern eine Klasse

War es hilfreich?

Lösung

Als jemand anders erwähnt, Kapitel 11 von Josh Blochs Effective Java ist ein unentbehrliche Ressource auf Java Serialisierung.

Ein paar Punkte aus diesem Kapitel relevant für Ihre Frage:

  • vorausgesetzt, Sie den Zustand der Nicht-serializable Feld in MyClass2 serialisiert werden wollen, muß das Feld MyClass, entweder direkt oder über Getter und Setter zugänglich sein. MyClass wird durch die Bereitstellung readObject- und write Methoden benutzerdefinierte Serialisierung implementieren müssen.
  • das nicht-serializable Feldes der Klasse muß eine API ist es Zustand (zum Schreiben auf das Objekt Stream) zu ermöglichen, hat immer und dann mit diesem Staat eine neue Instanz instanziieren (wenn später von dem Objekt Stream zu lesen.)
  • pro Artikel 74 von Effective Java, MyClass2 muß hat einen nicht-arg Konstruktor zugänglich MyClass, sonst ist es unmöglich für MyClass MyClass2 zu erweitern und implementieren Serializable.

Ich habe ein kurzes Beispiel geschrieben dies unten zeigt.


class MyClass extends MyClass2 implements Serializable{

  public MyClass(int quantity) {
    setNonSerializableProperty(new NonSerializableClass(quantity));
  }

  private void writeObject(java.io.ObjectOutputStream out)
  throws IOException{
    // note, here we don't need out.defaultWriteObject(); because
    // MyClass has no other state to serialize
    out.writeInt(super.getNonSerializableProperty().getQuantity());
  }

  private void readObject(java.io.ObjectInputStream in)
  throws IOException {
    // note, here we don't need in.defaultReadObject();
    // because MyClass has no other state to deserialize
    super.setNonSerializableProperty(new NonSerializableClass(in.readInt()));
  }
}

/* this class must have no-arg constructor accessible to MyClass */
class MyClass2 {

  /* this property must be gettable/settable by MyClass.  It cannot be final, therefore. */
  private NonSerializableClass nonSerializableProperty;

  public void setNonSerializableProperty(NonSerializableClass nonSerializableProperty) {
    this.nonSerializableProperty = nonSerializableProperty;
  }

  public NonSerializableClass getNonSerializableProperty() {
    return nonSerializableProperty;
  }
}

class NonSerializableClass{

  private final int quantity;

  public NonSerializableClass(int quantity){
    this.quantity = quantity;
  }

  public int getQuantity() {
    return quantity;
  }
}

Andere Tipps

MyClass2 ist nur eine Schnittstelle so techinicaly es keine Eigenschaften hat, nur Methoden. Davon abgesehen, wenn Sie Instanzvariablen haben, die sich nicht den einzigen Weg, serializeable Ich kenne zu umgehen, ist es diese Felder transiente zu erklären.

ex:

private transient Foo foo;

Wenn Sie ein Feld transient erklären wird es während der Serialisierung und Deserialisierung ignoriert werden. Beachten Sie, dass wenn Sie ein Objekt mit einem vorübergehenden Feld deserialisieren Wert dieses Feldes wird immer es ist standardmäßig (in der Regel null).

Beachten Sie können auch die readResolve () -Methode der Klasse, um außer Kraft setzen transiente Felder zu initialisieren basierend auf anderen Systemzustand.

Wenn möglich, die nicht serialiable Teile können als vorübergehende eingestellt werden

private transient SomeClass myClz;

Ansonsten können Sie verwenden Kryo . Kryo ist eine schnelle und effiziente Objektgraph-Serialisierung Rahmen für Java (z.B. Java-Serialisierung von java.awt.Color erfordert 170 Bytes, Kryo nur 4 Bytes), die auch nicht serializable Objekte serialisieren kann. Kryo kann auch automatisches tiefes und flaches Kopieren / Klonen durchzuführen. Dies ist die direkte Kopieren von Objekt zu Objekt, nicht object->bytes->object.

Hier ist ein Beispiel, wie man verwendet Kryo

Kryo kryo = new Kryo();
// #### Store to disk...
Output output = new Output(new FileOutputStream("file.bin"));
SomeClass someObject = ...
kryo.writeObject(output, someObject);
output.close();
// ### Restore from disk...
Input input = new Input(new FileInputStream("file.bin"));
SomeClass someObject = kryo.readObject(input, SomeClass.class);
input.close();

Serialized Objekte können auch durch die Registrierung exakte Serializer komprimiert werden:

kryo.register(SomeObject.class, new DeflateCompressor(new FieldSerializer(kryo, SomeObject.class)));

Wenn Sie MyClass2 ändern können, ist der einfachste Weg, dies zu adressieren ist die Eigenschaft transiente erklären.

Sie müssen writeObject() und readObject() und tun manuelle Serialisierung / Deserialisierung dieser Felder implementieren. Siehe die javadoc Seite für java.io.Serializable für weitere Einzelheiten. Josh Blochs Effective Java hat auch einige guten Kapitel über die Umsetzung der robuste und sichere Serialisierung.

Abhängig warum das Mitglied des MyClass2 nicht serialisierbar ist.

Wenn es einige gute Gründe ist, warum MyClass2 kann nicht in einer serialisierten Form dargestellt werden, dann sind die Chancen gut, aus dem gleichen Grund zu MyClass gilt, da es sich um eine Unterklasse ist.

Es kann möglich sein, eine benutzerdefinierte serialisiert Form für MyClass durch die Implementierung readObject- und write, so zu schreiben, dass der Zustand der MyClass2 Instanzdaten in MyClass kann in geeigneter Weise aus den serialisierten Daten neu erstellt werden. Dies wäre der Weg zu gehen, wenn MyClass2 API festgelegt ist und Sie können nicht hinzufügen Serializable.

Aber zuerst sollten Sie herausfinden, warum MyClass2 nicht serialisierbar ist, und vielleicht ändern.

Sie können durch einen Blick in das transiente Schlüsselwort beginnen, die Felder nicht Bestandteil des permanenten Status eines Objekts markiert.

Mehrere Möglichkeiten poped und ich wieder sie hier:

  • Implementieren write () und readObject- () als sk vorgeschlagen
  • die Eigenschaft transiente erklären und es wird nicht als erste von hank
  • angegeben serialisiert werden
  • verwenden XStream wie von boris-terzic
  • verwenden, um einen Serien Proxy als von tom-hawtin-tackline angegeben

XStream ist eine große Bibliothek zu tun schnellen Java XML-Serialisierung für jedes Objekt unabhängig davon, ob es ist Serializable oder nicht. Auch wenn das XML-Zielformat nicht zusagt, können Sie den Quellcode verwenden, um zu lernen, wie es geht.

Ein nützlicher Ansatz für Fälle von nicht-serialisierbaren Klassen (oder zumindest Subklassen) ist bekannt, einen seriellen Proxy Serialisierung. Im Wesentlichen writeReplace implementieren Sie eine Instanz von einer ganz anderen serializable Klasse zurückzukehren, die readResolve eine Kopie des ursprünglichen Objekts zurückzukehren implementiert. Ich schrieb ein Beispiel java.awt.BasicStroke auf Usenet serializing

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top