3

I have a problem with a static counter variable. In a super class ("Card") I have a variable that counts the amount of cards that gets registered (It's a ticket system). It is written like this:

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

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

The class implements Serializable and I use ObjectStream to write out the cards to a file.

But if I close the program and start it up again, it can read from the file and confirms and add the files to my cardregistry again. BUT, the card counter variable in the super class is reseted, and every new card I try to register starts from 001 again. What am I doing wrong? Cant seem to find anything about this particular problem on the net.

Solution: I used a DataOutputStream to save it on exit, and DataInputStream to read it on startup. I don't know if this is the most efficient way to do this, but it worked. Thanks alot for you comments, it helped me out alot!!!!

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.");
    }
}
fuLLMetaLMan
  • 165
  • 4
  • 17
  • 1
    @Aboutblank read the question – 0x6C38 Apr 23 '13 at 12:48
  • 1
    possible duplicate of [How to serialize static data members of a Java class?](http://stackoverflow.com/questions/1008023/how-to-serialize-static-data-members-of-a-java-class) – Duncan Jones Apr 23 '13 at 12:49

6 Answers6

7

Serialization does not persist the value of static variables. So when the class is loaded again, the default value (zero for static integer) is set. To persist the value, make the variable object level.

If you still want to preserve the values of static variables, you need to provide custom serialization using private void readObject(ObjectInputStream) and private void writeObject(ObjectOutputStream)

NOTE: Serializing the static variable with objects (by providing custom serialization) could lead to problems.

Think of the scenario: You create one Card object and serialize it. The static counter will be 1. The you create another object of card and serialize it. The static counter will be 2. So on you created 10 objects and serialized each of them. The static counter will be 10. So unless you deserialise the last object you won't get the correct value of the counter.

To avoid this problem and still store the count of the cards, you can create a wrapper class Cards

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

}

In the start first load (deserialize) the Cards object. Whenever you create Card object, add it to Cards (cardList) and the serialize the Cards object.

Apurv
  • 3,723
  • 3
  • 30
  • 51
  • I'm not sure if I understood that last bit about serializing the cards and wrapper class? I just stored the number in a file on program exit, and then loaded it in on program start. – fuLLMetaLMan Apr 23 '13 at 19:23
7

The counter is static. It is thus not part of the state of any Card instance, and serializing all your cards won't save the value of the counter.

Either save this counter value, reload it and reset it explicitely, or get the biggest ID from all the deserialized cards at startup an reset the counter to this max value.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
2

Static members are not getting serialized. They belong to the class, not to the class's instances that are getting serialized.

Lazarus Lazaridis
  • 5,803
  • 2
  • 21
  • 35
2

static fields are only static within the scope of one JVM i.e. if you stop execution,they lost their scope and data..

Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
1

static doesn't save/preserve the value when the program is closed and restarted. static modifier is used as a class level variable whose value remains same across any new object creation, and those objects can access that static value also through class level. 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

Now to preserve that static value you should save it to some file or db and on application restart, initialize that static value from there as necessary.

IConfused
  • 714
  • 2
  • 8
  • 20
0

As per Java specification static variables are not part of instances but they are part of Class level . While you serialize data, you do only for Object not for Class, So static will not be persisted.

When you reload the class after restarting it, it loads default value of the variable.

Alpesh Gediya
  • 3,706
  • 1
  • 25
  • 38