JAVA:类不会序列化



我一直在编写一个程序来学习更多关于JAVA的知识,现在我差不多完成了。我已经有一段时间没有使用Serialization了,即使在复习了它之后,我仍然缺少一些东西。我试图将这个类保存到一个文件中,但它抛出了一个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.GroupLayout"。删除GroupLayout后,"e.getMessage()"刚刚返回"omnitool.MonetaryField$1"。Omnitool是主要的软件包。这就是我剩下的地方。我刚刚试着为你们打印一个堆栈跟踪(e.getStackTrace().toString),但它只告诉我"[Ljava.lang.StackTraceElement;@6ab7501b"。。。如果有人能解释这意味着什么。此外,我已经对序列化进行了几个小时的研究,但如果有人能分享任何好的材料,那就太好了!

要打印出堆栈跟踪,我建议您使用

e.printStackTrace();

您似乎有一个名为keys的非transient字段,它是名为omnitool.MonetaryField$1的匿名内部类,它是不可序列化的,这也是它不会序列化的原因。您可以使它成为瞬态的,但您需要在反序列化时通过定义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.identitHashCode()很少有用。您需要像Throwable.printStackTrace()或Arrays.toString(array)这样的辅助函数,或者自己打印每个元素来查看它。

问题是某些字段无法序列化(因为它们没有实现java.io.Serializable接口)。

根据您向我们展示的内容,您应该选择:

transient KeyListener keys = new KeyListener() {

而不是

KeyListener keys = new KeyListener() {

此外,我没有看到您的类的源代码:SingleField。如果它没有实现java.io.Serializable接口,那么应该将所有这些字段标记为瞬态(或者确保实现了接口)。

相关内容

  • 没有找到相关文章

最新更新