我遇到静态计数器变量的问题。在超类(“卡”)中,我有一个变量来计算注册卡的数量(这是一个票务系统)。它是这样写的:
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.");
}
}
答案 0 :(得分: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
对象时,请将其添加到Cards
(cardList
)并序列化Cards
对象。
答案 1 :(得分:7)
计数器是静态。因此,它不属于任何Card 实例的状态,序列化所有卡片都不会保存计数器的值。
保存此计数器值,重新加载并明确重置,或者在启动时从所有反序列化卡中获取最大ID,并将计数器重置为此最大值。
答案 2 :(得分:2)
静态成员未被序列化。它们属于类,而不属于被序列化的类的实例。
答案 3 :(得分:2)
static fields
仅在static
范围内one JVM
,即如果您停止执行,则会丢失scope and data.
。
答案 4 :(得分:1)
static不保存/保留该值。 static修饰符用作类级别变量,其值在任何新对象创建中保持相同,并且这些对象也可以通过类级别访问该静态值。 e.g。
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
现在要保留该静态值,您应该将其保存到某个文件或db,并在应用程序重新启动时,根据需要从那里初始化该静态值。
答案 5 :(得分:0)
根据Java规范,静态变量不是实例的一部分,但它们是类级别的一部分。在序列化数据时,只能使用Object而不是Class,因此静态不会被保留。
重新启动后重新加载类时,它会加载变量的默认值。