Por que writeObject lança java.io.NotSerializableException e como faço para corrigir isso?

110

Eu tenho essa exceção e não entendo por que ela seria lançada ou como devo lidar com isso.

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

Onde elementestá um TransformGroupcontendo alguma outra TransformGroupsinstância da 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);
    }
}

O log de erros 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 (na classe Atom) é apenas uma classe personalizada que estende a aparência.

Mihai Bujanca
fonte
4
Parece que javax.media.j3d.TransformGroupele próprio não implementa Serializable
micha
Por que Atomambos se estendem Groupe têm um Groupmembro?
Marquês de Lorne

Respostas:

210

Os campos do seu objeto têm, por sua vez, seus campos, alguns dos quais não implementam Serializable. No seu caso, a classe ofensiva é TransformGroup. Como resolver isso?

  • se a aula é sua, faça Serializable
  • se a classe for de terceiros, mas você não precisar dela no formulário serializado, marque o campo como transient
  • se você precisa de seus dados e de terceiros, considere outros meios de serialização, como JSON, XML, BSON, MessagePack , etc. onde você pode obter objetos de terceiros serializados sem modificar suas definições.
Bozho
fonte
2
Bem, muito obrigado, será uma coisa muito difícil de fazer, uma vez que meus objetos existem apenas como parte do TransformGroup e não há nenhuma variável que os armazene. Meu aplicativo é um construtor de moléculas 3D, e todos os meus átomos e limites são apenas adicionados ao TransformGroup como instâncias - por exemplo, (new Atom ()). O problema não é apenas que eu preciso que eles sejam gravados em um arquivo, mas que o usuário pode querer remover ou editar os objetos atuais. Acho que vou tentar alguma serialização baseada em XML, mas sou um pouco novo no conceito e ainda é um pouco difícil para mim. Obrigado
Mihai Bujanca
15
Para adicionar a esta excelente resposta: se você precisa de seus dados e é de terceiros, você pode querer agrupar a classe de terceiros em sua própria classe, que implementa Serializablee usa readObject()e writeObject()serializar manualmente os dados da classe de terceiros. Em alguns casos, essa pode ser uma abordagem razoável. stackoverflow.com/a/12963580/1208581
sulai
76

java.io.NotSerializableExceptionpode ocorrer quando você serializa uma instância de classe interna porque:

serializar tal instância de classe interna resultará na serialização de sua instância de classe externa associada também

A serialização de classes internas (ou seja, classes aninhadas que não são classes-membro estáticas), incluindo classes locais e anônimas, é fortemente desencorajada

Ref: A interface serializável

Tho
fonte
5
Este foi o meu caso. Estava acontecendo quando peguei um atalho em um teste de unidade. Espero que esta resposta economize algum tempo para outra pessoa.
user489041
Eu tinha um campo privado final Set <ClaimsNode> outgoing = new TreeSet <ClaimsNode> (new Comparator <ClaimsNode> () {public int compare (ClaimsNode o1, ClaimsNode o2) {return o1.getNativeIndex () - o2.getNativeIndex (); }});
Vitaly Sazanovich de
1
Incrível, literalmente eu estava nisso há 1 hora. Comecei a duvidar que mesmo os ints primitivos não fossem serializáveis ​​e então me ocorreu que talvez algo esteja realmente errado aqui.
Shivam Pokhriyal
13

Torne a classe serializável implementando a interface java.io.Serializable.

  • java.io.Serializable - Interface do marcador que não contém métodos.
  • Objetivo da interface do marcador - informar ObjectOutputStreamque esse objeto é um objeto serializável.
Prabhakar
fonte
7
Você pode ler a pergunta, já está implementando Serializable. Ainda me surpreendem com 12+.
shaILU de