为什么会出现java.io.NotSerializableException:javax.swing.plaf.metal.MetalFileChooserUI?

| 我基本上想在Java中序列化一个ArrayList,这显然是需要更改的代码。 (编辑:粘贴整个类)
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.ArrayList;
import javax.swing.*;


public class GraphEditSerial extends JFrame{

    //stores all dots on the MainPanel
    private ArrayList<Circle> circles = new ArrayList<Circle>();

    class Circle implements Serializable{
        private static final long serialVersionUID = -8364830119753788192L;
        private int x, y;

        public String toString(){
            return \"(\"+x+\", \"+y+\")\";
        }

        public Circle(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    //variables for current workmode
    private boolean canInsert = false;
    private boolean canDelete = false;
    private boolean canMove = false;
    private boolean wasMoved = false;

    //defines a JPanel and adds a MouseListener
    class MainPanel extends JPanel implements MouseListener{

        //constructor
        public MainPanel(){
            setBackground(Color.white);
            addMouseListener(this);
        }

        //paints a blue spot on specified location
        public void paint(Graphics g) {
            super.paint(g);
            g.setColor(Color.blue);

            for (Circle k: circles) {
                g.fillOval(k.x - 5, k.y - 5, 10, 10);
            }
        }

        public void mouseClicked(MouseEvent e) {
            //user wants to add a circle
            if(canInsert){
                //adds new circle to ArrayList and displays all circles
                circles.add(new Circle(e.getX(), e.getY()));
                repaint();
            }
            //user wants to delete a circle
            else if(canDelete){
                //checking if clicked position is within 4px of existing circles
                for (int k=0; k<circles.size();k++){
                    Circle c = circles.get(k);
                    if(c.x-e.getX()<=4
                            &&c.x-e.getX()>=-4
                            &&c.y-e.getY()<=4
                            &&c.y-e.getY()>=-4){
                        //removes circle that is within 4 px of clicked position
                        circles.remove(k);
                    }
                }
                repaint();
            }
        }

        //used to move existing circles, but only if current workmode = move
        public void mousePressed(MouseEvent e) {
            //current workmode has to be \"move\"
            if(canMove==true){
                //checking if clicked position is within 4px of existing circles
                for (int k=0; k<circles.size();k++){
                    Circle c = circles.get(k);
                    if(c.x-e.getX()<=4
                            &&c.x-e.getX()>=-4
                            &&c.y-e.getY()<=4
                            &&c.y-e.getY()>=-4){
                        //removes circle that is within 4 px of clicked position
                        circles.remove(k);
                        wasMoved=true;
                    }
                }
            }
        }

        //displays moved circle at current position of mouse
        public void mouseReleased(MouseEvent e) {
            //current workmode has to be \"move\"
            if(canMove==true){
                //checking if user clicked on an existing circle before
                if(wasMoved==true){
                    circles.add(new Circle(e.getX(), e.getY()));
                    repaint();
                    wasMoved=false;
                }
            }
        }

        //not assigned
        public void mouseEntered(MouseEvent e) {}
        public void mouseExited(MouseEvent e) {}

    }

    //Menu
    JMenuBar mb      = new JMenuBar();
    JMenu graph      = new JMenu(\"Graph\");
    JMenu vertex     = new JMenu(\"Vertex\");
    JMenuItem open   = new JMenuItem(\"open\");
    JMenuItem mnew   = new JMenuItem(\"new\");
    JMenuItem save   = new JMenuItem(\"save\");
    JMenuItem insert = new JMenuItem(\"insert\");
    JMenuItem move   = new JMenuItem(\"move\");
    JMenuItem delete = new JMenuItem(\"delete\");
    JMenuItem none   = new JMenuItem(\"none\");

    //FileChooser
    JFileChooser fc;

    //main panel
    MainPanel main = new MainPanel();

    //bottom row
    JPanel bottomrow = new JPanel(new GridLayout(1,2));
    JLabel l1 = new JLabel(\"Selected Action:   \", SwingConstants.RIGHT);
    JTextField l2 = new JTextField(\"none\", SwingConstants.LEFT);

    //setting up a Menu with MenuItems, Dimensions, ActionListeners, etc...
    public GraphEditSerial(String s){

        super(s);

        //adding menu items to menus
        graph.add(open);
        graph.add(mnew);
        graph.add(save);
        vertex.add(insert);
        vertex.add(move);
        vertex.add(delete);
        vertex.add(none);

        fc = new JFileChooser();

        //Label l2 changes accordingly to selected MenuItem
        open.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                l2.setText(\"Graph: open\");
                canInsert=false; canDelete=false; canMove=false;
                repaint();

                int returnVal = fc.showOpenDialog(GraphEditSerial.this);
                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    File f = fc.getSelectedFile();
                    try{
                        FileInputStream fis = new FileInputStream(f);
                        ObjectInputStream ois = new ObjectInputStream(fis);
                        ArrayList<Circle> a = (ArrayList<Circle>)ois.readObject();
                        circles = a;
                        repaint();
                    }
                    catch (ClassNotFoundException e) {}
                    catch (IOException e){}
                }
            }
        });
        mnew.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                l2.setText(\"Graph: new\");
                canInsert=false; canDelete=false; canMove=false;
                //clears all vertexes
                circles.clear();
                repaint();
            }
        });
        save.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                l2.setText(\"Graph: save\");
                canInsert=false; canDelete=false; canMove=false;
                repaint();

                int returnVal = fc.showSaveDialog(GraphEditSerial.this);
                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    String datname = fc.getSelectedFile().getAbsolutePath().toString();
                    try{
                        FileOutputStream fos = new FileOutputStream(datname);
                        ObjectOutputStream oos = new ObjectOutputStream(fos);
                        oos.writeObject((ArrayList<Circle>) circles);
                        oos.close();
                    }
                    catch (IOException e){
                        l2.setText(e.toString());
                        e.printStackTrace();
                    }

                }
            }
        });
        insert.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                l2.setText(\"Vertex: insert\");
                canInsert=true; canDelete=false; canMove=false;
                repaint();
            }

        });
        move.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                l2.setText(\"Vertex: move\");
                canInsert=false; canDelete=false; canMove=true;
                repaint();
            }

        });
        delete.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                l2.setText(\"Vertex: delete\");
                canInsert=false; canDelete=true; canMove=false;
                repaint();
            }

        });
        none.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                l2.setText(\"none\");
                canInsert=false; canDelete=false; canMove=false;
                repaint();
            }

        });

        bottomrow.add(l1);
        bottomrow.add(l2);

        main.setPreferredSize(new Dimension(500,300));
        main.setOpaque(true);
        main.setBackground(Color.WHITE);

        mb.setPreferredSize(new Dimension(500, 20));
        mb.add(graph);
        mb.add(vertex);

        setJMenuBar(mb);
        add(main, BorderLayout.CENTER);
        add(bottomrow, BorderLayout.PAGE_END);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        pack();
        setVisible(true);
        setLocationRelativeTo(null);
    }

    public static void main(String[] arg){
        //new GraphEditor(\"MyGraphEditor\");
        new GraphEditSerial(\"MyGraphEditor\");
    }
}
我是在没有JFileChooser的情况下完成此操作的,只是指定了一个文件名,它就像一个魅力一样工作。我也可以毫无问题地反序列化它。但是,一旦我使用JFileChooser,就会得到\“ java.io.NotSerializableException:javax.swing.plaf.metal.MetalFileChooserUI \” 有人知道吗? 编辑:这是e.printStackTrace()打印的内容
java.io.NotSerializableException: javax.swing.plaf.metal.MetalFileChooserUI
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at javax.swing.event.EventListenerList.writeObject(Unknown Source)
at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteObject(Unknown Source)
at javax.swing.JComponent.writeObject(Unknown Source)
at sun.reflect.GeneratedMethodAccessor10.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteObject(Unknown Source)
at java.awt.Window.writeObject(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at java.awt.Window.writeObject(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at java.util.ArrayList.writeObject(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at GraphEditSerial$3.actionPerformed(GraphEditSerial.java:202)
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$000(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$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)
    
已邀请:
        
Circle
是您的UI类本身的内部类吗?如果它是一个内部类,而fc是一个外部类的字段,则
Circle
元素上的
writeObject
不仅会尝试序列化其字段,而且还将尝试对其外部类的字段进行序列化。而且,如果fc是外部类的一个字段,并且是MetalFileChooserUI,则它显然将无法序列化。 这是我可以从您的代码段中得出的最佳猜测。如果不能解决您的问题,如vanza所说,我们将需要有关ѭ2内容的更多信息     
        似乎您正在保存某个附加了此(匿名)ActionListener的对象,或者以某种方式引用了一个对象,而该对象又引用了此ActionListener。 ActionListener依次引用the6ѭ对象,即is7ѭ。 JFileChooser本身知道其UI对象(该对象完成所有工作,以使文件选择器适合您的系统),并且该对象不可序列化。 序列化JFileChooser没有意义。它将包含的唯一有趣的数据是文件名或目录名,无论如何它在另一个系统上都无法使用。 一个简单的解决方案是将“ 6”移到actionPerformed方法内部,然后在其中进行初始化(创建新的JFileChooser)。 但是您真的想看看为什么将ActionListener(或附加到它的对象)进行序列化-这有时可能有用,但是很可能您根本不希望对GUI进行序列化,而只对数据进行序列化。要有一些见识,改变
catch (IOException e){l2.setText(e.toString());}
catch (IOException e){
    l2.setText(e.toString());
    e.printStackTrace();
}
并查看标准输出中的堆栈跟踪。它应该显示一个提示,提示您尝试序列化哪些对象。可能是您的圈子确实引用了某些对象,但实际上不应该。 (或者应该是临时的引用。或者当它们不应该是内部类的对象时。)     
        我只是想添加有关该问题的其他信息,因为我碰到了这个错误(很可能是因为我是同一所大学的学生,并且讲师和任务完全相同:D)。 在这篇博文中,我详细分析了这个不利的星座:尝试将一个内部类与一个处理事件并使用jfilechooser的外部类进行序列化,但失败: http://hannes-schurig.de/21/11/2012/java-problem-beim-serialisieren-von-objekten-bei-der-verwendung-von-ereignishandlern-jfilechooser/ 它用德语显示,但我认为很容易理解,重要的内容已突出显示。     

要回复问题请先登录注册