JAVA: класс не будет сериализироваться

Я работал над программой, чтобы узнать больше о JAVA, и я почти закончил. Прошло много времени с тех пор, как я работал с сериализацией, и даже после того, как я ее освежил, я все еще что-то упускаю. Я пытаюсь сохранить этот класс в файл, но он вызывает исключение NotSerialzableException. Этот класс, MonetaryField, содержит не примитивный тип SingleField, который сериализуется и может быть сохранен на диск. Он также содержит следующее:

public class MonetaryField extends JPanel implements Serializable {

    private static final long serialVersionUID = 1L;
    public JLabel label;
    public SingleField gold;
    public SingleField silver;
    public SingleField copper;

    public MonetaryField() {

    }

    public MonetaryField(String s, boolean editable, boolean border) {
            label = new JLabel(s);
            gold = new SingleField("gold.png", border);
            silver = new SingleField("silver.png", border);
            copper = new SingleField("copper.png", border);
            gold.addKeyListener(keys);
            silver.addKeyListener(keys);
            copper.addKeyListener(keys);

            if(!editable) {
                    gold.setEditable(false);
                    silver.setEditable(false);
                    copper.setEditable(false);
            }
            GroupLayout layout = new GroupLayout(this);             
            this.setLayout(layout);
            layout.setHorizontalGroup(
                  layout.createSequentialGroup()
                      .addComponent(label)
                      .addComponent(gold)
                      .addComponent(silver)
                      .addComponent(copper)
        );
            layout.setVerticalGroup(
                  layout.createSequentialGroup()
                      .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                       .addComponent(label)
                       .addComponent(gold)
                       .addComponent(silver)
                       .addComponent(copper)
                    ));
    }

    public void setAmount(int g, int s, int c) {
            gold.setValue(g);
            silver.setValue(s);
            copper.setValue(c);
    }

    public void setAmount(String g, String s, String c) {
            gold.setValue(Integer.parseInt(g.replaceAll(",", "")));
            silver.setValue(Integer.parseInt(s.replaceAll(",", "")));
            copper.setValue(Integer.parseInt(c.replaceAll(",", "")));
    }

    public void setAmount(int amount) {
            gold.setValue(Math.floor(amount / 10000));
            silver.setValue(((amount % 10000) - (amount % 100)) / 100);
            copper.setValue(amount % 100);
    }

    public boolean sizeFits(Object field) {
            SingleField s_field = (SingleField) field;
            int max_chars = 4;
            boolean g = s_field.getText().length() < max_chars;
            if(!g) {
                    return false;
            }
            return true;
    }

    KeyListener keys = new KeyListener() {
            @Override
            public void keyTyped(KeyEvent e) {
                    if(!Character.isDigit(e.getKeyChar()) || sizeFits(e.getSource()) == false) {
                            e.consume();
                    }
            }

            @Override
            public void keyReleased(KeyEvent e) {    }

            @Override
            public void keyPressed(KeyEvent e) {    }
    };

    public double getAmount() {
            double d = 0.0;
            d += Double.parseDouble(gold.getText());
            d += Double.parseDouble(silver.getText())/100;
            d += Double.parseDouble(copper.getText())/10000;
            return d;
    }
}

В конце концов, это то, что я знаю: не примитивный тип SingleField НЕ является проблемой, поскольку он сериализирован и успешно сохраняется на диск. Когда я спросил "e.getCause()"в классе, сохраняющем это как данные, он сказал" null ". Когда я его вернул"e.getMessage"Виноват"javax.swing.GroupLayoutMsgstr "После удаления GroupLayout"e.getMessage()" только вернулся "omnitool.MonetaryField$1". Omnitool - основной пакет. Именно там я и остался. И я только что попытался напечатать трассировку стека для вас, ребята (e.getStackTrace(). ToString), но все, что он мне сказал, было"[Ljava.lang.StackTraceElement;@6ab7501b"... Если кто-нибудь может объяснить, что это значит. Кроме того, я уже провел несколько часов исследований по сериализации, но если у кого-нибудь есть какой-нибудь хороший материал, которым он мог бы поделиться, это было бы здорово!

2 ответа

Решение

Чтобы распечатать трассировку стека, я предлагаю вам использовать

e.printStackTrace();

Похоже, у вас нет transient поле называется keys который является анонимным внутренним классом под названием omnitool.MonetaryField$1 и это не Serializable и причина, по которой это не будет сериализовано. Вы можете сделать его временным, но вам потребуется пересоздать при десериализации, определив readObject метод

Из http://docs.oracle.com/javase/7/docs/api/java/io/ObjectInputStream.html вы можете определить

private void readObject(java.io.ObjectInputStream stream)
     throws IOException, ClassNotFoundException {
    stream.defaultReadObject();
    // re-initialise transient fields.
}

Я предлагаю вам не путать компоненты GUI с объектами передачи данных. Вы будете жить намного легче, если у вас есть классы, которые содержат чистые данные и легко сериализуются, а отдельные компоненты GUI визуализируют эти данные.


И я только что попытался напечатать трассировку стека для вас, ребята (e.getStackTrace(). ToString), но все, что он мне сказал, это "[Ljava.lang.StackTraceElement;@6ab7501b"... Если кто-нибудь может объяснить, что это значит,

Это означает, что Java array.toString не работает, и когда вы пытаетесь напечатать простой массив, он использует Object.toString(), который печатает класс и System.identHashCode(), что редко бывает очень полезно. Вам нужна вспомогательная функция, такая как Throwable.printStackTrace() или Arrays.toString(array), или напечатайте каждый элемент самостоятельно, чтобы увидеть его.

Проблема в том, что некоторые из ваших полей не могут быть сериализованы (так как они не реализуют java.io.Serializable интерфейс).

Из того, что вы показали нам, вы должны пойти на:

transient KeyListener keys = new KeyListener() {

скорее, чем

KeyListener keys = new KeyListener() {

Более того, я не вижу исходный код вашего класса: SingleField, Если он не реализует java.io.Serializable интерфейс, вы должны пометить все эти поля переходные (или убедитесь, что вы реализуете интерфейс).

Другие вопросы по тегам