Pourquoi writeObject lance-t-il java.io.NotSerializableException et comment le corriger?

110

J'ai cette exception et je ne comprends pas pourquoi elle serait lancée ou comment je devrais la gérer.

try {
    os.writeObject(element);
} catch (IOException e) {
    e.printStackTrace();
}

elementest un TransformGroupcontenant une autre TransformGroupsinstance de la classe Atom:

public class Atom extends Group implements Serializable{
    float pozX,pozY;
    Group group= new Group();   
    Color3f blue = new Color3f(new Color(255));
    Color3f black = new Color3f(new Color(0));
    Sphere AtSph=new Sphere();

    public Atom(final float WEIGHT, final int BOUNDS,final float radius,Color3f color)
    {
        AppSetting ap= new AppSetting(color, black);
        AtSph=new Sphere(radius,1,100,ap);
    }
}

Le journal des erreurs complet:

java.io.NotSerializableException: javax.media.j3d.TransformGroup
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at cls.MolecularBuilder.addAtom(MolecularBuilder.java:511)
    at cls.MolecularBuilder$Console.HidrogenItemActionPerformed(MolecularBuilder.java:897)
    at cls.MolecularBuilder$Console$2.actionPerformed(MolecularBuilder.java:746)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.AbstractButton.doClick(Unknown Source)
    at javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source)
    at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

AppSetting (dans la classe Atom) est simplement une classe personnalisée qui étend l'apparence.

Mihai Bujanca
la source
4
On dirait que javax.media.j3d.TransformGrouplui-même ne met pas en œuvre Serializable
micha
Pourquoi les Atomdeux étendent-ils Groupet ont-ils un Groupmembre?
Marquis de Lorne le

Réponses:

210

Les champs de votre objet ont quant à eux leurs champs, dont certains ne sont pas implémentés Serializable. Dans votre cas, la classe incriminée est TransformGroup. Comment le résoudre?

  • si le cours est à vous, faites-le Serializable
  • si la classe est tierce, mais que vous n'en avez pas besoin dans le formulaire sérialisé, marquez le champ comme transient
  • si vous avez besoin de ses données et qu'elles sont tierces, envisagez d'autres moyens de sérialisation, comme JSON, XML, BSON, MessagePack , etc. où vous pouvez obtenir des objets tiers sérialisés sans modifier leurs définitions.
Bozho
la source
2
Eh bien, merci beaucoup, ce sera une chose assez difficile à faire, car mes objets n'existent que dans le cadre du TransformGroup, et il n'y a aucune variable qui les stocke. Mon application est un constructeur de molécules 3D, et tous mes atomes et limites sont simplement ajoutés au TransformGroup en tant qu'instances - par exemple (new Atom ()). Le problème n'est pas seulement que j'ai besoin de les écrire dans un fichier, mais que l'utilisateur peut vouloir supprimer ou modifier les objets actuels. Je pense que je vais essayer une sérialisation basée sur XML, mais je suis assez nouveau dans le concept et c'est encore un peu difficile pour moi. Merci
Mihai Bujanca
15
Pour ajouter à cette excellente réponse: si vous avez besoin de ses données et qu'elles sont tierces, vous voudrez peut-être envelopper la classe tierce dans votre propre classe, qui implémente Serializableet utilise readObject()et writeObject()sérialise manuellement les données de la classe tierce. Dans certains cas, cela peut être une approche raisonnable. stackoverflow.com/a/12963580/1208581
sulai
76

java.io.NotSerializableExceptionpeut se produire lorsque vous sérialisez une instance de classe interne car:

la sérialisation d'une telle instance de classe interne entraînera également la sérialisation de son instance de classe externe associée

La sérialisation des classes internes (c'est-à-dire des classes imbriquées qui ne sont pas des classes membres statiques), y compris les classes locales et anonymes, est fortement déconseillée

Réf: L'interface sérialisable

Tho
la source
5
C'était le cas pour moi. Cela se passait lorsque j'ai pris un raccourci sur un test unitaire. J'espère que cette réponse fera gagner du temps à quelqu'un d'autre.
user489041
J'avais un champ privé final Set <ClaimsNode> outgoing = new TreeSet <ClaimsNode> (nouveau comparateur <ClaimsNode> () {public int compare (ClaimsNode o1, ClaimsNode o2) {return o1.getNativeIndex () - o2.getNativeIndex (); }});
Vitaly Sazanovich
1
Incroyable, littéralement j'étais dans ça pendant 1 heure. J'ai commencé à douter que même les ints primitifs ne soient pas sérialisables et puis il m'est venu à l'esprit que peut-être que quelque chose ne va vraiment pas ici.
Shivam Pokhriyal
13

Rendez la classe sérialisable en implémentant l'interface java.io.Serializable.

  • java.io.Serializable - Interface de marqueur qui ne contient aucune méthode.
  • Objectif de l'interface de marqueur - pour indiquer ObjectOutputStreamque cet objet est un objet sérialisable.
Prabhakar
la source
7
Vous pouvez lire la question, sa mise en œuvre déjà Serializable. Encore 12+ me surprennent.
shaILU