51 votes

Sérialisation Java avec pièces non sérialisables

J'ai:

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

Dans MyClass2, une propriété n'est pas sérialisable. Comment puis-je sérialiser (et désérialiser) cet objet?

Correction: MyClass2 n'est bien sûr pas une interface mais une classe.

49voto

Scott Bale Points 4385

Comme quelqu'un l'a noté, le chapitre 11 de Josh Bloch est Efficace Java est indispensable de ressources sur la Sérialisation Java.

Quelques points de ce chapitre pertinent à votre question:

  • en supposant que vous souhaitez pour sérialiser l'état de la non-sérialisable champ dans MyClass2, ce champ doit être accessible à MyClass, que ce soit directement ou par l'intermédiaire des getters et setters. MyClass aurez à mettre en œuvre la sérialisation personnalisée en fournissant des méthodes readObject et writeObject.
  • le non sérialisable du champ de la Classe doit avoir une API pour permettre l'obtention de son état (pour l'écriture sur le flux d'objet), puis de l'instanciation d'une nouvelle instance avec cet état (lorsque plus tard la lecture à partir du flux d'objet.)
  • par l'Article 74 de Efficace Java, MyClass2 doit avoir un pas-arg constructeur accessibles à MyClass, sinon il est impossible pour MyClass étendre MyClass2 et Sérialisable.

J'ai écrit un petit exemple ci-dessous illustre cette.


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;
  }
}

34voto

Mike Deck Points 7443

MyClass2 est juste une interface afin de techinicaly il n'a pas de propriétés, seules les méthodes. Cela étant dit, si vous avez des variables d'instance qui sont eux-mêmes pas serializeable le seul moyen que je connaisse pour obtenir autour, c'est de déclarer les champs transitoires.

ex:

private transient Foo foo;

Lorsque vous déclarez un champ transitoire, il sera ignoré lors de la sérialisation et de désérialisation processus. Gardez à l'esprit que lorsque vous désérialiser un objet avec un transitoire champ valeur du champ sera toujours par défaut (généralement la valeur null.)

Remarque vous pouvez également remplacer la readResolve() de votre classe afin d'initialiser transitoire des champs en fonction d'autres de l'état du système.

15voto

Radim Burget Points 116

Kryo est un framework de sérialisation de graphe d'objet rapide et efficace pour Java. Kryo peut également effectuer des copies / clonages automatiques profonds et superficiels. Il s'agit d'une copie directe d'un objet à l'autre et non de object->bytes->object .

Voici un exemple d'utilisation du kryo

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

11voto

ykaganovich Points 8497

Si vous pouvez modifier MyClass2, le moyen le plus simple de résoudre ce problème est de déclarer la propriété transitoire.

6voto

sk. Points 3690

Vous devrez implémenter writeObject () et readObject () ainsi que la sérialisation / désérialisation manuelle de ces champs. Voir la page javadoc pour java.io.Serializable pour plus de détails. Effective Java de Josh Bloch contient également de bons chapitres sur la mise en œuvre d'une sérialisation robuste et sécurisée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X