8
votes

Pourquoi java.lang.void n'est-il pas sérialisé?

Il est possible de sérialiser le «vide» primitif par défaut, pourquoi l'objet «vide» s'étend sur Serializable?

Exemple ajouté: strong> P>

La rotinimployation Demandez à une erreur de compilation disant «void ne se situant pas dans sa liaison» car elle ne s'étend pas sérialisable. Bien que «Somemethod» soit déclaré avec «Void», ce ne serait pas un problème. P>

public interface Root<R extends Serializable> extends Serializable {
  R someMethod();
}

public class RootImplementation implements Root<Void> {
  public Void someMethod() {
    return null;
  }
}


5 commentaires

Il n'y a pas de vide primitif. Et NOID n'a jamais eu d'instance, et je ne peux pas penser à un cas d'utilisation où ce serait un champ sur une classe. Mais si c'est le cas, vous pouvez toujours le rendre transitoire, car il sera toujours null de toute façon.


Qu'entendez-vous par «il est possible de sérialiser le« voilé »primitif par défaut»? Il n'y a pas de données à sérialiser ... Pouvez-vous donner un exemple de ce que vous voulez dire?


Jon Skeet peut sérialiser void !


Vous peut Serialize Void, principalement B / C, vous ne pouvez pas avoir d'instance de la classe (constructor.setabixible (true) et dangereux.AllocateInstance (void.class) ne compte pas)


Note latérale: Sérialisable est censé être une interface implicite / marquage.


9 Réponses :


4
votes

Le Javadoc est clair:

La classe de vide est une non négligeable classe d'espace réservé pour tenir une référence à l'objet de la classe représentant le Mot-clé Java

Parce que vous ne pouvez pas l'utiliser, il n'a pas besoin d'être sérialisable (sauf les trucs de réflexion).


Et pour la deuxième question: void! = vide (si vous pensez à! = dans une expression non Java)

oui void est un mot clé et void une classe.


0 commentaires

1
votes

Pour citer les Javadocs:

La classe Void est une classe d'espace réservée insensante pour contenir une référence à l'objet de la classe représentant le mot clé Java vide.

Étant donné que la classe est insensantasible, elle ne peut pas être désérialisée. ERGO Aucun besoin de soutien de sérialisation.


0 commentaires

0
votes

Il est possible de sérialiser le primitif 'vide' par défaut, pourquoi pas l'objet 'vide' s'étendre Sérialisable?

vide ne porte pas de valeur, donc cela n'a aucun sens de le sérialiser.

Cela ne signifie-t-il pas que VOID! = vide?

vrai, juste comme int! = Entier. Mais lorsque vous serialisez et désérialisez deux INTS, newint == oldint (je veux dire int , pas integer !!!). Aucune construction de ce type ne serait possible avec void . Cela n'a rien de sens pour ne rien sérialiser.


0 commentaires

0
votes

Ce serait utile que si vous aviez un champ de type void, ce qui n'a aucun sens. Vous auriez également besoin d'attribuer une instance, ce qui n'a pas de sens. Tant que vous ne le faites pas, vous pouvez sérialiser l'instance de la classe contenant le champ vide. Afin de créer une instance de vide, vous devez utiliser la réflexion afin d'utiliser le constructeur privé.

public class VoidSerializerDemo implements Serializable {
    private Void v;

    public static void main(String[] args) throws Exception {
        final VoidSerializerDemo instance = new VoidSerializerDemo();
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        final ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(instance);
        System.out.println("OK: null works");
        final Constructor<Void> constructor = Void.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        instance.v = constructor.newInstance();
        oos.reset();
        System.out.println("Going to throw");
        oos.writeObject(instance);
    }
}


0 commentaires

0
votes

D'autres ont expliqué pourquoi il n'a pas de sens pour un type qui ne peut jamais être instancié à mettre en œuvre sérialisable et pourquoi vide n'est pas une primitive ou sérialisable. < / p>

Pour résoudre le code de votre édition, je pense que vous devriez simplement modifier le r étend sérialisable lié ​​à juste r . La plupart des types génériques sérialisable n'exigent pas que leurs paramètres de type soient sérialisables ... Ils indiquent simplement que si vous leur mettez quelque chose qui n'est pas sérialisable, ils ont gagné 't être sérialisable non plus. Il s'agit généralement d'une bonne pratique, car il est essentiel d'essayer trop fort pour appliquer la sérialisalisabilité au niveau du compilateur peut vous mordre (comme vous le voyez ici).


0 commentaires

6
votes

OK, en réponse à votre exemple, non si vous avez changé la méthode sur VOID , il ne fonctionnerait pas, car la méthode doit avoir un type de retour (même si Java permet désormais des types de retour covariant dans méthodes remplacées). La discussion sur void confond le problème.

Ce que vous voulez faire est de déclarer un paramètre de type en tant que "retournera NULL". Le vide est généralement un bon choix pour cela, mais pour le voivenir au travail, le type de retour doit être objet. Le vide ne peut pas implémenter chaque interface dans l'API simplement parce que quelqu'un pourrait vouloir l'utiliser pour indiquer un retour nul sur un paramètre de type.

Il y a trois façons de regarder votre problème:

  1. Serializable est une déclaration de type trop restrictive. Vous devriez vraiment utiliser l'objet. Avez-vous vraiment besoin que cela soit sérialisé?
  2. Vous pouvez simplement déclarer le paramètre de type comme sérialisable et, dans la pratique, retour null. Ce dons n'indique pas complètement que vous retournez NULL à chaque fois, mais cela peut suffire.
  3. Vous pouvez déclarer votre propre classe appelée NULL qui implémente sérialisable, peut-être comme une classe imbriquée statique de l'interface racine, et utilisez-la comme le paramètre de type dans ce cas. Vous trouverez de faire votre propre objet NULL n'est pas si rare, même dans le JDK standard, il y a (un privé).

2 commentaires

Merci d'avoir répondu. 1. À mesure que Colind mentionne; La plupart desserront la Serialziable du type générique car la déclaration de classe elle-même implique de ne pas enregistrer des objets non sérialisables sur la mise en œuvre. Bien que aussi peu de gens vont utiliser l'interface et faire des implémentations, je souhaite que cela soit aussi utile que possible de ne pas faire une erreur. 2. Je ne veux pas que l'extension éventuelle soit capable de retourner autre chose que le vide (ou NULL dans ce cas depuis le vide doit être utilisé). 3. Voici comment j'ai fait pour le moment, même si je voulais poser la question et voir si quelqu'un avait une meilleure solution.


@Tomas Forsman, une classe implémentée Serializable ne signifie pas que cela peut être sérialisé. Considérez ceci: Vid vide privé WriteObject (ObjectOutputSteam Out) {Jetez NOUVELLE NOTSERIALIZABLEEXCEPTION (GetClass (). GetName ());} J'utilise cela pour vous assurer que certaines classes étendues n'atteignent jamais le formulaire de sérialisation.



0
votes

VOID est uniquement destiné à montrer qu'une méthode ne peut que renvoyer null , malheureusement, il n'y a aucun moyen de déclarer le type null directement. Pour le void JVM, seul un objet d'extension normal de classe normale et, en tant que tel, ne peut pas être utilisé en place pour d'autres classes ou interfaces, cela facilite votre exemple.

Étant donné que votre méthode ne renvoie rien, mais null, vous pouvez remplacer le vide avec quelque chose comme ce qui suit: xxx

s'appelle d'une primitive, le vide montre l'absence d'une valeur , une méthode renvoyant le vide ne renvoie pas une valeur de type vide à la place, il ne renvoie pas littéralement rien.


0 commentaires

2
votes

Je vais le mettre ici en tant que Comminity-wiki

​​Tu peux (DE) Serialize java.lang.void code> B / C Vous pouvez l'initialiser avec NULL uniquement. Java ne se soucie pas si une classe implémente java.io.rsérialisable code> si c'est null code>. P>

résultat du code p>

  public class VoidOut implements java.io.Serializable{
    int x=1;
    Void v = null;

    public static void main(String[] args) throws Throwable{
        VoidOut v = new VoidOut();
        System.out.println(v);
        ByteArrayOutputStream b =new ByteArrayOutputStream(256);
        ObjectOutputStream o = new ObjectOutputStream(b);
        o.writeObject(v);
        o.close();
        ObjectInputStream in =new ObjectInputStream(new ByteArrayInputStream(b.toByteArray()));
        System.out.println(in.readObject());        
    }
}


0 commentaires

0
votes

Si vous utilisez une bibliothèque Apache Commons, il y a un org.apache.commons.lang3.Objectutils.Null qui s'étend sérialisable.


0 commentaires