我一直致力于一个程序,以了解更多有关JAVA的知识,我差不多完成了。自从我使用序列化以来已经有一段时间了,甚至在刷完它之后,我仍然缺少一些东西。我正在尝试将此类保存到文件中,但它会抛出NotSerialzableException。这个类MonetaryField包含非原始类型SingleField,它是Serialized并且可以保存到磁盘。它还包含以下内容:
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不是问题,因为它是Serialized并成功保存到磁盘。当我在类中查询“e.getCause()
”时将其保存为数据,它表示“null”。当我将其返回“e.getMessage
”时,它将其归咎于“javax.swing.GroupLayout
”。删除GroupLayout后,“e.getMessage()
”刚刚返回“omnitool.MonetaryField$1
”。 Omnitool是主要的包。这就是我离开的地方。我刚才试图为你们打印一个堆栈跟踪(e.getStackTrace()。toString),但它告诉我的只是“[Ljava.lang.StackTraceElement;@6ab7501b
”......如果有人能解释这意味着什么。此外,我已经对序列化进行了几个小时的研究,但如果有人有任何可以分享的好材料,那就太好了!
答案 0 :(得分:6)
要打印堆栈跟踪,建议您使用
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),或者自己打印每个元素以查看它。
答案 1 :(得分:0)
问题是您的某些字段无法序列化(因为它们没有实现java.io.Serializable
接口)。
根据您向我们展示的内容,您应该选择:
transient KeyListener keys = new KeyListener() {
而不是
KeyListener keys = new KeyListener() {
此外,我没有看到您班级的源代码:SingleField
。如果它没有实现java.io.Serializable
接口,则应将所有这些字段标记为瞬态(或确保实现接口)。