Question

J'ai une classe qui est destiné à un usage immuable, donc je voudrais étiqueter tous les champs final.

Cependant, la classe est sérialisé et désérialisé d'envoyer sur le réseau. Pour que cela fonctionne un constructeur vide est nécessaire. Cela me empêche de créer les champs final.

Je suis sûr que cela est un problème assez commun, mais je ne peux pas trouver une solution. Comment dois-je procéder?

Était-ce utile?

La solution

Dans le cas typique de sérialisation, il est pas nécessaire que la classe a un constructeur vide ou champs non-finale sérialisable.

Maintenant, si vous devez faire votre propre sérialisation, ou vous avez besoin de sous-classe d'une classe qui ne met pas en œuvre Serializable, ce qui est une autre histoire.

Vous devez fournir quelques détails sur la façon dont vous avez un problème.

Autres conseils

Un constructeur sans arg n'est pas nécessaire. La plus classe dérivée non-serialisable a besoin d'un constructeur sans arg disponible au moins la plus classe dérivée serialisable.

Si vous avez besoin de muter les champs dans un readObject, puis utiliser un proxy série par readResolve et writeReplace.

Cette question est ouvert bug sur le langage Java . (Notez que cela ne vaut que si vous avez à faire la sérialisation manuellement, comme avec readObject)

Pour faire écho à ce qui a été dit, non-arg les constructeurs ne sont pas une exigence si vous prenez la route de la mise en œuvre de l'interface java.io.Serializable. Jetez un coup d'oeil au code source java.lang.Integer par exemple, une simple classe sérialisable / immuable qui a deux constructeurs: celui qui prend un int, et qui prend une chaîne. Code source: http://www.docjar.com/html /api/java/lang/Integer.java.html . Javadoc: http://java.sun.com/ JavaSE / 6 / docs / api / java / lang / Integer.html .

En outre, selon la complexité de votre classe et ce que vous faites, vous pourriez envisager de mettre en œuvre sérialisation via l'interface java.io.Externalizable (bien que certains considèrent pas à jour, et il n'a pas besoin d'un constructeur sans arg). Voici un aperçu sur le SO: Quelle est la différence entre Serializable ? et Externalizable en Java , et voici le tutoriel Java officiel: http://java.sun.com/docs/books/tutorial/javabeans/persistence/index.html .

Pour mémoire, puisque j'ai eu un problème similaire:
J'ai eu un message " java.io.InvalidClassException: com.example.stuff.FooBar; com.example.stuff.FooBar, pas de constructeur valide "

Je pensais que c'était parce qu'il manquait un constructeur par défaut. Mais les réponses ci-dessus confirment qu'il est pas obligatoire (mais notre application. Utilise un vieux sérialiseur qui nécessitent en effet un constructeur par défaut, de sorte que le cas peut se).

Je trouve une page indiquant:

  

Si une classe qui est conçu pour l'héritage n'est pas sérialisable, il   peut être impossible d'écrire une sous-classe sérialisable. Plus précisément,   sera impossible si la superclasse ne fournit pas accessible   constructeur sans paramètre.

D'où le message que je suis arrivé, je suppose. Il est apparu que la question fondamentale était classique: je déclarais une classe sérialisable, mais la superclasse était pas! Je me suis déplacé vers le haut de l'interface Serializable dans la hiérarchie, et tout allait bien.

Mais le message était un peu trompeur ...: -)

Un constructeur sans arg n'est pas nécessaire. Lisons le code source:

// java.io.ObjectStreamClass
private static Constructor<?> getSerializableConstructor(Class<?> cl) {
    Class<?> initCl = cl;
    while (Serializable.class.isAssignableFrom(initCl)) {
        if ((initCl = initCl.getSuperclass()) == null) {
            return null;
        }
    }
    ...
}

Alors, en fait le constructeur sans arg est nécessaire dans la classe la plus proche non Serializable dans la hiérarchie de type.

Cela signifie que le Domain de classe suivante peut être sérialisé.

class Domain implements Serializable {
    private final int a;

    public Domain(int a) {
      this.a = a;
    }
}

Mais la Son de classe ne peut pas:

class Father{
  private final int a;

  public Father(int a) {
    this.a = a;
  }
}

class Son extends Father implements Serializable {
  public Son(int a) {
    super(a);
  }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top