Static Variables in Java: Class vs Instance Variables
Two different objects, two different assignments — counter1.b = 3; and counter2.b = 4; — yet printing b from either object shows 4 both times. That is not a bug: the field b is declared static, so both objects share the exact same memory slot.
A static variable (also called a static field or class variable) in Java is a field declared inside a class with the static keyword. It belongs to the class itself, not to any individual object: there is exactly one copy for the whole class, it is created once when the class is loaded and initialized, and it can be accessed without creating an object.
What does static mean in Java
The static keyword marks a member of a class — a variable, a method, or a nested class — as belonging to the class rather than to any particular instance. A non-static (instance) member can only be reached through an object of its class. A member declared static is available without any object reference at all, directly through the class name. Broader background on classes and objects is covered in Classes and Objects in Java.
When you create objects, no copies of a static variable are made: no matter how many objects exist, there is still just one static variable for the whole class. Static fields are sometimes compared to global variables, but that comparison is loose — Java has no true global variables. A static field always belongs to a specific class, and its visibility is still controlled by access modifiers such as private or public (see Access Modifiers in Java).
Like instance fields, static variables get default values if not explicitly initialized: 0 for numeric types, false for boolean, null for reference types.
Static vs instance variables: an example
Let's compare an instance variable and a static variable side by side. To reach the instance variable a you need an object of the class Counter. The variable b can be reached without any object — even without the class name, if the code is inside the same class:
public class Counter {
int a;
static int b;
public static void main(String[] args) {
Counter counter = new Counter();
System.out.println(counter.a);
System.out.println(b);
}
}
How to access a static variable
From another class, a static variable should be accessed through the class name: Counter.b. Technically it can also be accessed through any object of the same class, such as counter1.b, but that style is discouraged: it misleads readers into thinking the field is per-object, and most IDEs flag it with a warning.
public class CounterExample {
public static void main(String[] args) {
Counter counter1 = new Counter();
Counter counter2 = new Counter();
System.out.println(Counter.b); // recommended: access through the class name
System.out.println(counter1.b); // compiles, but discouraged
counter1.b = 3;
counter2.b = 4;
System.out.println(counter1.b);
System.out.println(counter2.b);
}
}
Output:
0
0
4
4 Both assignments changed the very same variable, so the last value written, 4, shows up through either object.
Best practice
Always access a static variable through its class name, Counter.b, rather than through an object, counter1.b. It makes it immediately clear that the value is shared across all instances.
Class variable vs instance variable
| Characteristic | Instance variable (object field) | Static variable (class field) |
|---|---|---|
| Declaration | int a; | static int b; |
| Number of copies | One per object | One per class |
| When it is created | When the object is created (new) | Once, when the class is loaded and initialized |
| How to access it | Through an object: obj.a | Through the class name: Counter.b |
| Access from a static method | Only through an object reference | Directly |
| Typical use | State of a specific object (color, name) | Counters, constants, shared settings |
Example: counting created objects
A classic use case for a static variable is counting how many objects of a class have been created. Let's declare a static variable count in a class Ball and increment it inside the constructor, since the constructor runs every time a new object is created. Because count is private, a static method getCount() exposes it:
public class Ball {
private static int count = 0;
String color = "none";
public Ball(String color) {
this.color = color;
count++;
}
public static int getCount() {
return count;
}
} public class BallExample {
public static void main(String[] args) {
Ball ball1 = new Ball("red");
Ball ball2 = new Ball("blue");
System.out.println("Number of created objects: "
+ Ball.getCount());
}
} Output:
Number of created objects: 2 Each ball has its own color, but count is shared: both constructor calls incremented the same variable.
Constants: static final
The most common real-world use of static variables is declaring constants. A constant combines two modifiers: static (one value per class) and final (the value cannot change after it is assigned). By convention, constant names are written in uppercase with underscores:
public class AppConfig {
public static final int MAX_USERS = 100;
public static final String APP_NAME = "ExamClouds";
public static final double TAX_RATE = 0.2;
} public class AppConfigExample {
public static void main(String[] args) {
System.out.println(AppConfig.APP_NAME + ": " + AppConfig.MAX_USERS);
// AppConfig.MAX_USERS = 200; // compile error: cannot assign a value to final variable
}
} If a constant of a primitive type or String is initialized with an expression that is known at compile time, the compiler inlines its value at every place it is used — this is called a compile-time constant. Such constants can be used, for example, as labels in a switch statement's case.
Nuance
final on a reference variable prevents reassigning the reference itself, not the contents of the object it points to. The constant static final List<String> NAMES = new ArrayList<>(); still allows calling NAMES.add(...). For a truly immutable collection, use List.of(...).
Where developers go wrong with static variables
- Declaring a local variable static. Writing
static int x = 0;inside a method body is a compile error. Thestaticmodifier is only valid on class members (fields, methods, nested types) and on initializer blocks (static { ... }), never on local variables. - Reaching an instance field from a static method. Inside
main()or any other static method, you cannot simply writeaifais a non-static field — the compiler reports non-static variable cannot be referenced from a static context. You need an object:new Counter().a. - Shared mutable state. A static variable is visible from every object and every thread. The operation
count++is not atomic, so whenBallobjects are created from multiple threads concurrently, the counter can silently lose increments. In multi-threaded code, useAtomicIntegeror proper synchronization instead. - Overusing static. If a value logically belongs to one specific object (a ball's color, a user's name), it should not be static — otherwise every object ends up overwriting the same shared field.
For deeper context on how static members relate to object lifecycle and memory, see Java Memory Structure: Stack and Heap and the final keyword in Java.
Frequently Asked Questions
Where are static variables stored in memory?
In modern HotSpot JVMs, the values of static fields live on the heap, attached to the java.lang.Class object of their class (they moved there from PermGen already in JDK 7). Java 8 then removed PermGen entirely and replaced it with Metaspace, which stores class metadata but not the values of static fields themselves.
Can you access a static variable through a null reference?
Yes, and it's a popular interview question. The code Counter c = null; System.out.println(c.b); does not throw NullPointerException: the compiler resolves member access through the variable's declared (compile-time) type, not through the object's runtime value, effectively Counter.b, and the object itself is never used.
Are static variables inherited in Java?
A subclass can access a non-private static field of its parent, even through its own name (Child.count), but no new copy is created — parent and child share the single variable. If the subclass declares a static field with the same name, it does not override the parent's field; it hides it, and which one you get depends on the class name used to access it.
Does Java have a const keyword?
const is a reserved word in Java, but it is not used for anything — you cannot declare a variable with it. Constants in Java are created by combining static and final, for example public static final int MAX_USERS = 100;.
What is the difference between static and final in Java?
static decides who owns the variable: the class (a single shared copy) or each object (its own copy). final decides whether it can be reassigned after the initial value is set. The two are independent: you can have a static variable without final (a counter), a final field without static (an immutable per-object id), or both together, which gives you a constant.
When is a static variable initialized?
Once, during class initialization — before the first object is created, the first static method is called, or the first static field is accessed (compile-time constants are the exception). Static field initializers and static blocks run in the order they appear in the class.
Comments