2013-04-23 11 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规范,静态变量不是实例的一部分,但它们是类级别的一部分。当你序列化数据时,你只为对象而不是类,所以静态不会被持久化。

重新启动后重新加载类时,它会加载该变量的默认值。