我基本上想在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是外部类的字段,则writeObject元素上的Circle不仅会尝试序列化其字段,而且还将尝试序列化其外部类的字段。而且,如果fc是外部类的一个字段,并且是MetalFileChooserUI,则显然它将失败序列化。

这是我可以从您的代码段中得出的最佳猜测。如果不能解决您的问题,如vanza所说,我们将需要有关Circle内容的更多信息

09-27 08:48