Declaring Static Member Variables
A static member variable is shared by all instances of its class, so it holds one value for the class as a whole.
A Number That Describes the Whole Class
Suppose a program has a class that holds a number describing the whole class rather than any one object made from it. A count of how many players are in a poker game is a good example. Each player might be represented by an object, but the number of players belongs to the game as a whole. Where should that number live, and how does code in another class reach it?
A static member variable answers both questions. It is declared inside a class, and it holds one value for the class as a whole. This article follows that value through three moments: when it is created and shared, when it is read from inside its own class, and when it is read from a different class. Along the way you will see what happens when one object changes it.
Where a Shared Value Lives
A static member variable is shared by all instances of its class, so it holds one value for the class as a whole. Instances are the individual objects created from the class. Because the variable belongs to the class rather than to any one object, there is a single variable that every object of that class refers to.
Contrast this with a non-static member variable. Each object created from a class gets its own separate copy of a non-static variable, so changing it in one object does not change it in another. A static member variable is different: there is one copy for the whole class, no matter how many objects are created. The diagram below shows this difference for three objects of the same class.
Read the diagram carefully. The static variable count appears once, at the top, with a single value. The three per-object counts are separate boxes, each with its own value, and they are not the static variable. The per-object entries are shown only to make the contrast visible: a non-static variable would have one box for every object, while a static variable has only one box for the entire class.
Reading the Value Inside Its Own Class
Here is the poker situation written as Java code. The class Poker declares a static member variable named numberOfPlayers. Code inside Poker can name the variable directly, with no class name in front of it. The declaration uses the static keyword and is public, which the source describes as the clearest case of a static member variable that can be used from outside its class.
public class Poker {
public static int numberOfPlayers = 0;
public static void addPlayer() {
numberOfPlayers = numberOfPlayers + 1;
}
public static void showPlayers() {
System.out.println(numberOfPlayers);
}
}- 1Line 2 declares the static member variable
numberOfPlayersand gives it the starting value 0. - 2Lines 4 to 6 define
addPlayer. The line inside it readsnumberOfPlayers, adds 1, and stores the result back in the same variable. - 3Lines 8 to 10 define
showPlayers, which prints the current value using the plain namenumberOfPlayers. - 4Neither method needs the words Poker dot in front of the variable, because both are written inside the class that defines it.
numberOfPlayersis declared static, so one value is stored for the whole Poker classaddPlayerrefers tonumberOfPlayersby its plain nameshowPlayersalso uses the plain name, because it is inside the defining class
Reaching the Value from Another Class
Code in a different class cannot rely on the plain name alone. It must write a compound identifier. The form is the class name, then a dot, then the variable name, written as class-name.variable-name. The dot joins the two parts into one identifier that tells the reader exactly which class owns the variable.
The source gives two familiar examples from everyday Java. The System class contains the public static member variable out, which is used in other classes as System.out. The Math class contains the public static member variable PI, which is used as Math.PI. In both cases the class name comes first, then the dot, then the variable name. Every time you write System.out.println, you are using this same pattern.
4- Poker.numberOfPlayers is the compound identifier used from a different class
- The plain name
numberOfPlayerswould not work here, because Table is not the defining class
Following One Change Across Objects
Because a static member variable has only one value for the class, a change made through one object is visible through every other object. Follow the value of numberOfPlayers as two objects of Poker take turns. Before you read the answer, decide what the second object will see.
What do you think happens?
The first object sets numberOfPlayers to 4. What value does the second object read from numberOfPlayers?
Reveal answer
4
A static member variable is shared by all instances of its class. There is only one stored value, so the second object reads the same 4 that the first object wrote.
The diagram shows one stored value moving from 3 to 4. The second object does not hold its own copy that needs updating, because it reads the one shared variable. A non-static variable would behave differently: each object would hold its own value, and writing to one object's copy would leave the others unchanged.
Mistakes With Shared Values
The following mistakes are common when students first work with static member variables. Each one comes from treating the variable as if it belonged to a single object.
Common mistake Writing only the plain name from another class
What it looks likeTable code that writes numberOfPlayers = 4 when numberOfPlayers is defined in Poker
Why it failsThe plain name is only meaningful inside the defining class. Outside it, the name does not identify which class owns the variable.
Do this insteadWrite the compound identifier Poker.numberOfPlayers in the other class.
Common mistake Reversing the parts of the compound identifier
What it looks likeWriting numberOfPlayers.Poker instead of Poker.numberOfPlayers
Why it failsThe class name must come first, then the dot, then the variable name. The source gives the form as class-name.variable-name.
Do this insteadPut the class name before the dot and the variable name after it.
Common mistake Expecting each object to keep its own count
What it looks likeAssuming that a second object created from Poker starts with a fresh numberOfPlayers of 0
Why it failsA static member variable is shared by all instances of its class, so there is one value for the whole class.
Do this insteadTreat the value as belonging to the class, and use a non-static variable when each object needs its own value.
Common mistake Forgetting that a change made through one object is visible to every other object
Tracking Games in GuessingGame
The source applies the same idea to a GuessingGame class from earlier in its chapter. Two static member variables are added. The first, gamesPlayed, keeps track of how many games the user has played. The second, gamesWon, keeps track of how many of those games the user has won. Both are static because each describes the game as a whole, not a single round.
Counting games across rounds
A GuessingGame class has static member variables gamesPlayed and gamesWon, both starting at 0. A user plays three rounds and wins two of them. What are the final values, and where do they live?
- 1Identify the scope
Both variables describe the whole game, so both are static and each has one value for the class.
- 2Count the rounds
Each finished round increases
gamesPlayedby 1, so after three roundsgamesPlayedis 3. - 3Count the wins
Each won round increases
gamesWonby 1, so after two winsgamesWonis 2. - 4Check the storage
Because both are static, the values are stored once for the class, not once for each round object that may be created.
gamesPlayed is 3 and gamesWon is 2, stored as single values for the GuessingGame class.
Practice Reading Compound Identifiers
A class named Counter declares a public static member variable named count. Write the statement that a different class, Report, would use to print the value of count. Then say which part of your identifier names the class, which part names the member, and what the dot connects.
Hints
- Inside Report, the plain name count would not identify Counter's variable.
- The form is class-name.variable-name, with the class name first.
- The answer has the shape Counter.count inside a print statement.
Two objects are created from Poker. The first object adds one player with addPlayer, and then the second object adds one more. Using the shared-value idea, what does numberOfPlayers hold after both calls, and why does the second object's call not start from 0?
Hints
- There is only one
numberOfPlayersfor the whole class. - Think about what the first call stored, and where the second call reads from.
Key Takeaways
- A static member variable is shared by all instances of its class, so it holds one value for the class as a whole rather than one value per object.
- Inside the class that defines a static member variable, the plain variable name is enough to reach it.
- From a different class, the variable must be written as the compound identifier class-name.variable-name, as in
System.outandMath.PI. - A change made through one object to a static member variable is seen by every other object of that class, because all of them refer to the same single value.