0

私は 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.GroupLayout。GroupLayout を削除した後、" e.getMessage()" は " " を返しomnitool.MonetaryField$1ました。Omnitool がメイン パッケージです。私が残っている場所です。そして、皆さんのためにスタック トレース (e.getStackTrace().toString) を印刷しようとしましたが、「[Ljava.lang.StackTraceElement;@6ab7501b」とだけ言われました... 誰かがそれが何を意味するのか説明できるなら。また、シリアライゼーションに関する数時間の調査をすでに行っていますが、誰かが共有できる良い資料を持っていれば、それは素晴らしいことです!

4

2 に答える 2

6

スタックトレースを印刷するには、使用することをお勧めします

e.printStackTrace();

呼び出された匿名の内部クラスである非transientフィールドが呼び出されたようで、これはシリアライズ可能ではなく、これがシリアライズされない理由です。一時的にすることはできますが、メソッドを定義して逆シリアル化で再作成する必要がありますkeysomnitool.MonetaryField$1readObject

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) などのヘルパー関数が必要になるか、各要素を自分で印刷して表示します。

于 2013-08-03T06:36:13.873 に答える
0

問題は、一部のフィールドをシリアル化できないことです (java.io.Serializableインターフェイスを実装していないため)。

あなたが私たちに示したものから、あなたは行くべきです:

transient KeyListener keys = new KeyListener() {

それよりも

KeyListener keys = new KeyListener() {

さらに、あなたのクラスのソースコードが表示されません: SingleField. インターフェースを実装していない場合はjava.io.Serializable、これらのフィールドをすべて一時的なものとしてマークする必要があります (またはインターフェースを実装していることを確認してください)。

于 2013-08-03T06:43:09.087 に答える