3

静的カウンター変数に問題があります。スーパークラス(「カード」)には、登録されるカードの量をカウントする変数があります(チケットシステムです)。次のように書かれています。

public class Card implements Serializable    {
    private int id;
    public static int nextNr= 000;
    Card next;

    public Card(int t)   {
        id= ++nextNr;
        next= null;
    }
}

このクラスは Serializable を実装し、ObjectStream を使用してカードをファイルに書き出します。

しかし、プログラムを閉じて再度起動すると、ファイルから読み取って確認し、ファイルをカードレジストリに再度追加できます。しかし、スーパークラスのカードカウンター変数はリセットされ、登録しようとするすべての新しいカードは再び001から始まります。私は何を間違っていますか?ネット上でこの特定の問題について何も見つけられないようです。

解決策: DataOutputStream を使用して終了時に保存し、DataInputStream を使用して起動時に読み取りました。これがこれを行う最も効率的な方法かどうかはわかりませんが、うまくいきました。コメントありがとうございます、とても助かりました!!!!

abstract public class Card implements Serializable  {

private int type;
private int cardNr;
private static int nextNr = readCardNr();
Card next;   //COllections or not.. hmmmm

public Card(int t)   {
    cardNr= ++nextNr;
    next= null;
    type = t;
    writeCardNr();
}

public int getType(){
    return type;
}

public void setCardNr(int i) {
    cardNr= i;
}
public int getCardNr()  {
    return cardNr;
}


public static int readCardNr() {        
    try(DataInputStream inn= new DataInputStream(new FileInputStream("KortNummer")))   {
        nextNr= inn.readInt();
        inn.close();
        return nextNr;
    }
    catch(FileNotFoundException fnfe)   {
        skrivMld("Fant ingen tidligere registrerte kort. Starter nytt kortregister.");
        nextNr= 000;
        return nextNr;
    }
    catch(EOFException eofe)    {
        System.out.println("End of file");
    }
    catch(IOException ioe)  {
        skrivMld("Feilmelding: IO Exception");
    }
    return nextNr;
}

public void writeCardNr()    {
    try(DataOutputStream ut= new DataOutputStream(new FileOutputStream("KortNummer"))){
        ut.writeInt(cardNr);
    }
    catch(IOException ioe)  {
        skrivMld("Problem med skriving til fil.");
    }
}
4

6 に答える 6

7

シリアル化は、静的変数の値を保持しません。そのため、クラスが再度ロードされると、デフォルト値 (静的整数の場合はゼロ) が設定されます。値を永続化するには、変数をオブジェクト レベルにします。

それでも静的変数の値を保持したい場合は、 と を使用してカスタム シリアル化を提供する必要がありますprivate void readObject(ObjectInputStream)private void writeObject(ObjectOutputStream)

注: (カスタムのシリアル化を提供することによって) オブジェクトを使用して静的変数をシリアル化すると、問題が発生する可能性があります。

シナリオを考えてみましょう。Card オブジェクトを 1 つ作成し、それをシリアル化します。静的カウンターは になります1。カードの別のオブジェクトを作成し、それをシリアル化します。静的カウンターは になります2。10 個のオブジェクトを作成し、それぞれをシリアル化しました。静的カウンターは になります10。したがって、最後のオブジェクトを逆シリアル化しない限り、カウンターの正しい値を取得できません。

この問題を回避し、カードの数を保存するには、ラッパー クラスを作成できます。Cards

public class Cards implements Serializable    {
    private List<Card> cardList = new ArrayList<Card>();
    // getter and setter

}

最初に、Cardsオブジェクトをロード (デシリアライズ) します。オブジェクトを作成するたびに、それを( )Cardに追加し、オブジェクトをシリアル化します。CardscardListCards

于 2013-04-23T12:48:40.220 に答える
7

カウンターは静的です。したがって、これは Cardインスタンスの状態の一部ではなく、すべてのカードをシリアル化してもカウンターの値は保存されません。

このカウンター値を保存し、リロードして明示的にリセットするか、起動時にデシリアライズされたすべてのカードから最大の ID を取得して、カウンターをこの最大値にリセットします。

于 2013-04-23T12:49:32.527 に答える
2

static fieldsstaticつまり、one JVM実行を停止すると、それらは失われますscope and data.

于 2013-04-23T12:58:24.453 に答える
2

静的メンバーがシリアル化されていません。それらは、シリアル化されているクラスのインスタンスではなく、クラスに属しています。

于 2013-04-23T12:50:05.880 に答える
1

static は、プログラムを閉じて再起動したときに値を保存/保持しません。static修飾子は、値が新しいオブジェクトの作成全体で同じままであるクラスレベル変数として使用され、それらのオブジェクトはクラスレベルからもその静的値にアクセスできます。例えば

public class A{
public static int val = 0;
public int verify = 0;
public A(){
val++;
}
}

A a = new A();      // val = 1
A b = new A();      // val = 2
A c = new A();      // val = 3

a.verify = A.val;   // val = 3
b.verify = A.val;   // val = 3
c.verify = A.val;   // val = 3

その静的な値を保存するには、ファイルまたはデータベースに保存し、アプリケーションの再起動時に、必要に応じてそこからその静的な値を初期化する必要があります。

于 2013-04-23T12:54:13.023 に答える
0

Java 仕様によると、静的変数はインスタンスの一部ではありませんが、クラス レベルの一部です。データをシリアル化する間、クラスではなくオブジェクトに対してのみ行うため、静的は永続化されません。

再起動後にクラスをリロードすると、変数のデフォルト値がロードされます。

于 2013-04-23T12:58:49.473 に答える