81 votes

comment tester en Java qu'une classe implémente correctement Serializable (il ne s'agit pas simplement d'une instance de Serializable)

Je me suis mise en œuvre d'une classe Sérialisable (c'est donc un objet de valeur pour une utilisation w/ RMI). Mais j'ai besoin de le tester. Est-il un moyen de le faire facilement?

précisions: je suis la mise en œuvre de la classe, de sorte qu'il est trivial de bâton Serializable dans la définition de classe. J'ai besoin d'manuellement sérialiser/désérialiser pour voir si elle fonctionne.

J'ai trouvé ce C# question, est-il une semblable réponse pour Java?

134voto

skaffman Points 197885

L'été simple est de vérifier que l'objet est une instance d' java.io.Serializable ou java.io.Externalizable, mais ce n'est pas vraiment prouver que l'objet est vraiment serializable.

La seule façon d'en être sûr c'est de l'essayer pour de vrai. Le test le plus simple est quelque chose comme:

new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(myObject);

et vérifier qu'il ne lance pas d'exception.

Apache Commons Lang fournit un peu plus version brève:

SerializationUtils.serialize(myObject);

et encore une fois, vérifiez en faveur de l'exception.

Vous pouvez être plus rigoureux encore, et vérifiez qu'il désérialise de nouveau dans quelque chose d'égal à l'original:

Serializable original = ...
Serializable copy = SerializationUtils.clone(original);
assertEquals(original, copy);

et ainsi de suite.

30voto

Jason S Points 58434

méthodes utilitaires basées sur la réponse de skaffman:

 private static <T extends Serializable> byte[] pickle(T obj) 
       throws IOException 
{
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(baos);
    oos.writeObject(obj);
    oos.close();
    return baos.toByteArray();
}

private static <T extends Serializable> T unpickle(byte[] b, Class<T> cl)
       throws IOException, ClassNotFoundException 
{
    ByteArrayInputStream bais = new ByteArrayInputStream(b);
    ObjectInputStream ois = new ObjectInputStream(bais);
    Object o = ois.readObject();
    return cl.cast(o);
}
 

3voto

TofuBeer Points 32441

Ce code devrait le faire ...

 import java.io.ByteArrayOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;

public class Main
{
    public static void main(String[] args)
    {
        System.out.println(isSerializable("Hello"));
        System.out.println(isSerializable(new Main()));
    }

    public static boolean isSerializable(final Object o)
    {
        final boolean retVal;

        if(implementsInterface(o))
        {
            retVal = attemptToSerialize(o);
        }
        else
        {
            retVal = false;
        }

        return (retVal);
    }

    private static boolean implementsInterface(final Object o)
    {
        final boolean retVal;

        retVal = ((o instanceof Serializable) || (o instanceof Externalizable));

        return (retVal);
    }

    private static boolean attemptToSerialize(final Object o)
    {
        final OutputStream sink;
        ObjectOutputStream stream;

        stream = null;

        try
        {
            sink   = new ByteArrayOutputStream();
            stream = new ObjectOutputStream(sink);
            stream.writeObject(o);
            // could also re-serilalize at this point too
        }
        catch(final IOException ex)
        {
            return (false);
        }
        finally
        {
            if(stream != null)
            {
                try
                {
                    stream.close();
                }
                catch(final IOException ex)
                {
                    // should not be able to happen
                }
            }
        }

        return (true);
    }
}
 

3voto

Andrzej Doyle Points 52541

La réponse courte est, vous pouvez venir avec quelques objets candidats et effectivement essayer de sérialiser eux à l'aide d'un mécanisme de votre choix. Le test est ici que l'absence d'erreurs lors marshalling/unmarshalling, et que la "réhydrater" de l'objet est égale à l'original.

Alternativement, si vous n'avez pas de candidat objets, vous pouvez mettre en œuvre une réflexion basée sur le test que introspecte la (non-statique, non transitoires) champs de votre classe afin de s'assurer qu'ils sont Sérialisables. Parlant d'expérience, cela devient étonnamment complexe étonnamment rapidement, mais il peut être fait dans une mesure raisonnable.

L'inconvénient de cette approche est que si un champ est par exemple List<String>, alors vous pouvez soit ne pas la classe pour ne pas avoir strictement serializable champ, ou simplement supposer qu'un serializable mise en œuvre de la Liste sera utilisée. Aucune n'est parfaite. (Vous l'esprit, ce dernier problème existe pour les exemples trop; si tous les exemples utilisés dans le test utilise serializable Listes, il n'y a rien pour empêcher un non sérialisable version utilisée par un autre code dans la pratique).

2voto

YoK Points 8221

Vous pouvez faire l'essai suivant:

  • Sérialiser un objet de fichier et de le rendre assurez-vous qu'aucune exception n'est levée.
  • En outre, désérialiser un objet en arrière et de les comparer avec l'objet original.

Voici l'exemple pour la sérialisation et la désérialisation d'un objet dans un fichier:

http://www.rgagnon.com/javadetails/java-0075.html

http://www.javapractices.com/topic/TopicAction.do?Id=57

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