Dlaczego writeObject zgłasza wyjątek java.io.NotSerializableException i jak to naprawić?

110

Mam ten wyjątek i nie rozumiem, dlaczego miałbym go wyrzucić ani jak mam sobie z tym poradzić.

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

Gdzie elementjest TransformGroupzawierający inną TransformGroupsinstancję klasy 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);
    }
}

Pełny dziennik błędów:

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 (w klasie Atom) to po prostu niestandardowa klasa, która rozszerza wygląd.

Mihai Bujanca
źródło
4
Wygląda na to, że javax.media.j3d.TransformGroupsam nie implementuje Serializable
micha
Dlaczego Atomzarówno rozszerza się, jak Groupi ma Groupczłonka?
Markiz Lorne

Odpowiedzi:

210

Pola twojego obiektu mają z kolei swoje pola, z których niektóre nie implementują Serializable. W twoim przypadku jest to klasa przestępcza TransformGroup. Jak to rozwiązać?

  • jeśli klasa jest twoja, zrób to Serializable
  • jeśli klasa należy do innej firmy, ale nie potrzebujesz jej w postaci serializowanej, zaznacz pole jako transient
  • jeśli potrzebujesz jego danych i jest to strona trzecia, rozważ inne sposoby serializacji, takie jak JSON, XML, BSON, MessagePack itp., gdzie możesz uzyskać serializację obiektów stron trzecich bez modyfikowania ich definicji.
Bozho
źródło
2
Cóż, wielkie dzięki, będzie to dość trudne, ponieważ moje obiekty istnieją tylko jako część TransformGroup i nie ma żadnych zmiennych, które je przechowują. Moja aplikacja jest konstruktorem cząsteczek 3D, a wszystkie moje atomy i granice są po prostu dodawane do TransformGroup jako instancje - np. (Nowy Atom ()). Problem polega nie tylko na tym, że potrzebuję ich zapisania do pliku, ale także na tym, że użytkownik może chcieć usunąć lub edytować bieżące obiekty. Myślę, że spróbuję trochę serializacji opartej na XML, ale jestem całkiem nowy w tej koncepcji i jest to dla mnie trochę trudne. Dziękuję
Mihai Bujanca
15
Aby dodać do tej doskonałej odpowiedzi: jeśli potrzebujesz jego danych i jest to strona trzecia, możesz chcieć zawinąć klasę strony trzeciej do własnej klasy, która implementuje Serializablei używa readObject()oraz writeObject()ręcznie serializować dane klasy strony trzeciej. W niektórych przypadkach może to być rozsądne podejście. stackoverflow.com/a/12963580/1208581
sulai
76

java.io.NotSerializableExceptionmoże wystąpić podczas serializacji wystąpienia klasy wewnętrznej, ponieważ:

serializacja takiej instancji klasy wewnętrznej spowoduje również serializację skojarzonej z nią instancji klasy zewnętrznej

Serializacja klas wewnętrznych (tj. Klas zagnieżdżonych, które nie są statycznymi klasami składowymi), w tym klas lokalnych i anonimowych, jest zdecydowanie odradzana

Ref: Interfejs szeregowy

Chociaż
źródło
5
Tak było w przypadku mnie. To się działo, kiedy poszedłem na skróty w teście jednostkowym. Mam nadzieję, że ta odpowiedź pozwoli zaoszczędzić trochę czasu komuś innemu.
user489041
Miałem prywatne końcowe pole Set <ClaimsNode> outgoing = new TreeSet <ClaimsNode> (nowy komparator <ClaimsNode> () {public int porównać (ClaimsNode o1, ClaimsNode o2) {return o1.getNativeIndex () - o2.getNativeIndex (); }});
Witalij Sazanowicz
1
Niesamowite, dosłownie kręciłem się w tym przez ostatnią godzinę. Zacząłem wątpić, że nawet prymitywne inty nie dają się serializować, a potem przyszło mi do głowy, że może coś tu jest naprawdę nie tak.
Shivam Pokhriyal
13

Uczyń klasę możliwą do serializacji, implementując interfejs java.io.Serializable.

  • java.io.Serializable - Interfejs Marker, który nie zawiera żadnych metod.
  • Cel interfejsu Marker - aby powiedzieć, ObjectOutputStreamże ten obiekt jest obiektem możliwym do serializacji.
Prabhakar
źródło
7
Możesz przeczytać pytanie, już zaimplementowano Serializable. Wciąż 12+ mnie zadziwia.
shaILU