2013-04-23 356 views
3

我有一個靜態計數器變量的問題。在一個超類(「卡」)中,我有一個變量來計算獲得註冊的卡的數量(這是一個票務系統)。它是這樣寫的:JAVA - 程序重啓時靜態變量重置

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將卡片寫出到文件中。

但是,如果我關閉程序並重新啓動它,它可以從文件中讀取並確認並再次將文件添加到我的cardregistry。但是,超類中的卡計數器變量被重置,並且我嘗試註冊的每個新卡都從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."); 
    } 
} 
+1

@ Aboutblank閱讀問題 – 2013-04-23 12:48:44

+1

可能重複[如何序列化Java類的靜態數據成員?](http://stackoverflow.com/questions/1008023/how-to-serialize-static-data-members- java-class) – 2013-04-23 12:49:47

回答

7

該計數器是靜態。因此它不是任何卡實例的狀態的一部分,並且序列化您的所有卡都不會保存計數器的值。

要麼保存這個計數器值,重新加載並明確地重置它,要麼在啓動時從所有反序列化的卡中獲得最大ID,並將計數器重置爲該最大值。

+0

謝謝!我在程序的出口處寫出了卡號,並在開始時讀取它,並且它工作正常! =) – fuLLMetaLMan 2013-04-23 19:21:30

7

序列化不會保留靜態變量的值。所以當類再次被加載時,默認值(靜態整數爲零)被設置。要堅持該值,請設置變量對象的級別。

如果仍想保留靜態變量的值,則需要使用private void readObject(ObjectInputStream)private void writeObject(ObjectOutputStream)

注意提供自定義的序列:序列化與對象(通過提供自定義序列化)的靜態變量可能會導致問題。

考慮這種情況:您創建一個Card對象並對其進行序列化。靜態計數器將是1。您創建卡的另一個對象並對其進行序列化。靜態計數器將是2。因此,您創建了10個對象並將它們序列化。靜態計數器將是10。所以除非你反序列化最後一個對象,否則你將無法獲得正確的計數值。

爲了避免這個問題,但還是存儲卡的數量,你可以創建一個包裝類Cards

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

} 

在開始第一負載(反序列化)的Cards對象。無論何時創建Card對象,將它添加到CardscardList)和序列化Cards對象。

+0

我不知道我是否理解了關於序列化卡片和包裝類的最後一點? 我剛剛在程序退出時將該數字存儲在一個文件中,然後在程序啓動時加載它。 – fuLLMetaLMan 2013-04-23 19:23:58

2

靜態成員沒有被序列化。它們屬於類,而不屬於正在序列化的類的實例。

1

當程序關閉並重新啓動時,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 

我們保留靜態值,你應該把它保存到某些文件或數據庫和應用重啓,初始化靜態值從那裏進行必要的。

2

static fields只是staticone JVM即範圍之內,如果你停止執行,他們失去了scope and data.

0

按照Java規範,靜態變量不是實例的一部分,但它們是類級別的一部分。當你序列化數據時,你只爲對象而不是類,所以靜態不會被持久化。

重新啓動後重新加載類時,它會加載該變量的默認值。