¿Por qué writeObject lanza java.io.NotSerializableException y cómo lo soluciono?

110

Tengo esta excepción y no entiendo por qué se lanzaría o cómo debería manejarla.

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

Donde elementes un que TransformGroupcontiene alguna otra TransformGroupsinstancia de la clase 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);
    }
}

El registro de errores completo:

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 (en la clase Atom) es solo una clase personalizada que extiende Apariencia.

Mihai Bujanca
fuente
4
Parece que en javax.media.j3d.TransformGroupsí mismo no implementa Serializable
micha
¿Por qué Atomambos se extienden Groupy tienen un Groupmiembro?
Marqués de Lorne

Respuestas:

210

Los campos de su objeto tienen a su vez sus campos, algunos de los cuales no se implementan Serializable. En su caso, la clase infractora es TransformGroup. ¿Cómo resolverlo?

  • si la clase es tuya, hazla Serializable
  • si la clase es de un tercero, pero no la necesita en el formulario serializado, marque el campo como transient
  • si necesita sus datos y es un tercero, considere otros medios de serialización, como JSON, XML, BSON, MessagePack , etc., donde puede obtener objetos de terceros serializados sin modificar sus definiciones.
Bozho
fuente
2
Bueno, muchas gracias, será bastante difícil de hacer, ya que mis objetos solo existen como parte del TransformGroup, y no hay ninguna variable que los almacene. Mi aplicación es un constructor de moléculas 3d, y todos mis átomos y límites simplemente se agregan al TransformGroup como instancias, por ejemplo (new Atom ()). El problema no es solo que los necesito escritos en un archivo, sino que el usuario puede querer eliminar o editar los objetos actuales. Creo que intentaré una serialización basada en XML, pero soy bastante nuevo en el concepto y todavía me resulta un poco difícil. Gracias
Mihai Bujanca
15
Para agregar a esta excelente respuesta: si necesita sus datos y es un tercero, es posible que desee empaquetar la clase de terceros en su propia clase, que implementa Serializabley usa readObject()y writeObject()serializa manualmente los datos de la clase de terceros. En algunos casos, este podría ser un enfoque razonable. stackoverflow.com/a/12963580/1208581
sulai
76

java.io.NotSerializableExceptionpuede ocurrir cuando serializa una instancia de clase interna porque:

serializar una instancia de clase interna de este tipo dará como resultado la serialización de su instancia de clase externa asociada también

Se desaconseja encarecidamente la serialización de clases internas (es decir, clases anidadas que no son clases miembro estáticas), incluidas las clases locales y anónimas

Ref: La interfaz serializable

aunque
fuente
5
Este fue mi caso. Estaba sucediendo cuando tomé un atajo en una prueba unitaria. Espero que esta respuesta le ahorre tiempo a alguien más.
user489041
Tenía un campo privado Final Set <ClaimsNode> saliente = new TreeSet <ClaimsNode> (new Comparator <ClaimsNode> () {public int compare (ClaimsNode o1, ClaimsNode o2) {return o1.getNativeIndex () - o2.getNativeIndex (); }});
Vitaly Sazanovich
1
Increíble, literalmente estuve en esto durante la última hora. Comencé a dudar de que incluso los ints primitivos no fueran serializables y luego se me ocurrió que tal vez algo estuviera realmente mal aquí.
Shivam Pokhriyal
13

Haga que la clase sea serializable implementando la interfaz java.io.Serializable.

  • java.io.Serializable - Interfaz de marcador que no tiene ningún método.
  • Propósito de la interfaz de marcador: decirle ObjectOutputStreamque este objeto es un objeto serializable.
Prabhakar
fuente
7
Puede leer la pregunta, ya está implementando Serializable. Todavía 12+ me sorprende.
shaILU