61 votes

Comment gérer un "champ d'instance non sérialisable non transitoire dans une classe sérialisable"?

Considérons la classe ci-dessous. Si je lance Findbugs contre, il me donne une erreur ("Non-transitoire non sérialisable champ d'instance dans la classe sérialisable") sur la ligne 5, mais pas sur la ligne 7.

1 public class TestClass implements Serializable {
2
3  private static final long serialVersionUID = 1905162041950251407L;
4
5  private Set<Integer> mySet;      // Finsbugs error
6
7  private HashSet<Integer> myOtherSet;
8
9 }

C'est correct parce que java.util.Ensemble jamais implémente Serializable dans sa hiérarchie et java.util.HashSet n'. Toutefois, il est préférable de code à l'aide d'interfaces plutôt que des implémentations concrètes.

Comment puis-je mieux gérer cela?

Je peux ajouter un @Suppresswarnings(justification="Pas de bug", les valeurs="SE_BAD_FIELD") sur la ligne 3. J'ai beaucoup d'Ensembles et de Listes dans mon code et je suis peur qu'il la litière de mon code de trop.

Sont t-il de meilleures façons de faire?

32voto

Michael Borgwardt Points 181658

Toutefois, il est préférable de code à l'aide d'interfaces au lieu de béton les implémentations.

J'affirme que non, dans ce cas, il ne l'est pas. Findbugs tout à fait correctement vous dit que vous êtes courir le risque en NotSerializableException dès que vous avez un non-sérialisable Set mise en œuvre dans ce domaine. C'est quelque chose que vous devriez faire. Comment, cela dépend de la conception de vos classes.

  • Si ces collections sont initialisés au sein de la classe et de ne jamais mettre de l'extérieur, je ne vois absolument rien de mal à déclarer le type de béton pour le champ, puisque les champs sont des détails de mise en œuvre de toute façon. Ne pas utiliser le type d'interface dans l'interface publique.
  • Si la collection sont passés dans la classe par l'intermédiaire d'une interface publique, vous avez pour vérifier qu'ils sont en fait Serializable. Pour ce faire, créer une interface SerializableSet extends Set, Serializable et l'utiliser pour votre domaine. Alors, soit:
    • Utiliser SerializableSet dans l'interface publique. Le problème, c'est que vous pouvez pas utiliser cette interface avec une plaine Set.
    • Vérifiez les collections transmise à l'intermédiaire de la classe instanceof Serializable et de lever une exception si elles ne le sont pas, sinon de les jeter à l' SerializableSet

12voto

Graham Points 106

Je sais que c'est une vieille question à laquelle on a déjà répondu, mais pour que tout le monde sache, vous pouvez définir le champ Set<Integer> comme transitoire si vous ne souhaitez pas sérialiser ce champ particulier qui corrigera votre erreur FindBugs.

 public class TestClass implements Serializable {

    private static final long serialVersionUID = 1905162041950251407L;
    private transient Set<Integer> mySet;

}
 

Je préfère cette méthode au lieu de forcer les utilisateurs de votre API à transtyper vers votre type concret, à moins que ce ne soit simplement interne, la réponse de Michael Borgwardt est plus logique.

9voto

jontejj Points 725

Vous pouvez utiliser un assistant de capture pour vous assurer qu'un ensemble transmis prend en charge deux interfaces:

 private static class SerializableTestClass<T extends Set<?> & Serializable> implements Serializable
{
    private static final long serialVersionUID = 1L;
    private final T serializableSet;

    private SerializableTestClass(T serializableSet)
    {
        this.serializableSet = serializableSet;
    }
}

public static class PublicApiTestClass
{
    public static <T extends Set<?> & Serializable> Serializable forSerializableSet(T set)
    {
        return new SerializableTestClass<T>(set);
    }
}
 

De cette manière, vous pouvez avoir une API publique qui applique Serializable sans vérifier / exiger des détails d'implémentation spécifiques.

7voto

brabenetz Points 71

J'utilise un filtre findbugs-exclude pour les champs collection:

 <Match>
    <Field type="java.util.Map" />
    <Bug pattern="SE_BAD_FIELD" />
</Match>
<Match>
    <Field type="java.util.Set" />
    <Bug pattern="SE_BAD_FIELD" />
</Match>
<Match>
    <Field type="java.util.List" />
    <Bug pattern="SE_BAD_FIELD" />
</Match>
 

Voir http://findbugs.sourceforge.net/manual/filter.html

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