static is one keyword that trips up beginners because it quietly changes who owns a member — the class or the object. Get that one idea, and static variables, static methods, and the mysterious static in public static void main all click at once.
This tutorial explains static through the lens of ownership, with runnable code for each use. It assumes you already know how classes and objects relate; if not, skim that first because static only makes sense once you know what an object normally owns.
The core idea: class-level vs object-level
When you create an object, it gets its own copy of every instance field. Ten Student objects have ten separate name fields. A static member breaks that rule: there is exactly one copy, owned by the class, shared by every object and even reachable with no object at all.
Think of it as the difference between "each student's roll number" (instance — different per object) and "the total number of students enrolled" (static — one shared counter for the whole class).
Static variables: one shared copy
A static variable is declared with static inside the class but outside any method. Every instance sees and modifies the same variable.
class Student {
static int totalStudents = 0; // one shared counter
String name; // one per object
Student(String name) {
this.name = name;
totalStudents++; // affects the shared copy
}
}
public class Main {
public static void main(String[] args) {
new Student("Anitha");
new Student("Ravi");
new Student("Priya");
System.out.println(Student.totalStudents); // prints 3
}
}
What to notice: each Student has its own name, but they all share one totalStudents. We read it as Student.totalStudents — through the class, not an object — which signals that it belongs to the class. Creating three students bumps the single counter to 3.
Pro tip: Access static members through the class name (
Student.totalStudents), not through an object (anitha.totalStudents). Both compile, but the object form misleads readers into thinking the value is per-object. Good IDEs even warn you about accessing a static member via an instance.
Static methods: call without an object
A static method belongs to the class, so you call it without creating an instance. This is exactly how utility methods work — Math.max(), Integer.parseInt(), and Collections.sort() are all static.
class MathUtil {
static int square(int n) {
return n * n;
}
}
public class Main {
public static void main(String[] args) {
// no object needed
System.out.println(MathUtil.square(5)); // prints 25
}
}
The restriction that catches beginners: a static method cannot directly access instance variables or call instance methods, because there is no particular object for it to work on. It can freely touch other static members.
class Counter {
int instanceValue = 10;
static int staticValue = 20;
static void show() {
System.out.println(staticValue); // fine: static
// System.out.println(instanceValue); // compile error: no object
}
}
The reasoning is not arbitrary. show() might be called as Counter.show() when zero Counter objects exist — so which instanceValue would it read? There is no answer, so the compiler forbids it.
Why main is static
This is the interview question hidden in plain sight. public static void main is static because the JVM must call it to start your program, and at that moment no object of your class exists yet.
If main were an instance method, the JVM would need a HelloWorld object to call it — but creating that object is your program's job, which hasn't started. Static breaks the deadlock: the JVM calls main on the class directly, before any object is born. You met this signature in your first Java program; now you know why every word of it, including static, is mandatory.
Static blocks: run-once initialization
A static block runs once, when the class is first loaded, before main and before any object is created. Use it to initialize static data that a simple assignment can't handle.
class Config {
static String environment;
static {
// runs once at class load, before main
environment = System.getenv("APP_ENV");
if (environment == null) {
environment = "development";
}
System.out.println("Config loaded: " + environment);
}
}
public class Main {
public static void main(String[] args) {
System.out.println("Using " + Config.environment);
}
}
The static block prints before main's line, because class loading (and its static block) happens the first time you touch Config. If you declare multiple static blocks, they execute top to bottom in source order.
Interview note: A favorite trap is predicting the print order of a static block, an instance initializer, and a constructor. The rule: static blocks run once at class load; then for each object, instance initializers and the constructor run in order. Practice these output-prediction questions on our Java OOP interview questions page.
Static vs instance: a side-by-side
| Aspect | static (class-level) |
Instance (object-level) |
|---|---|---|
| Copies in memory | One, shared | One per object |
| Accessed via | Class name | Object reference |
| Created when | Class loads | Object is constructed |
| Can access instance members? | No, not directly | Yes |
| Typical use | Constants, counters, utilities | Object-specific data |
A clean rule of thumb: if a value or behavior is genuinely the same for the whole class and doesn't depend on any single object's data, make it static. Otherwise keep it as an instance member.
Memory location reinforces the difference. Instance fields live inside each object on the heap, so they come and go as objects are created and garbage-collected. Static fields belong to the class itself and are set up once when the class is loaded, living for as long as the class stays loaded — effectively the whole program in most cases. That single, long-lived copy is exactly why a static counter can track values across every object while an instance field cannot.
static final: the constant pattern
The one static usage nobody argues about is static final, which creates a named constant shared by the whole class and never reassigned.
class Circle {
static final double PI = 3.14159; // one shared, unchangeable value
double area(double radius) {
return PI * radius * radius;
}
}
PI is static because every circle uses the same value, and final because it must never change. Java's own libraries use this everywhere — Integer.MAX_VALUE and Math.PI are both public static final constants. Naming them in UPPER_SNAKE_CASE is the standard convention so readers instantly recognize a constant.
Common mistakes with static
- Mutable static state in multithreaded code. A shared static variable changed by many threads is a classic race condition. When you reach multithreading, you will see why shared mutable static fields need synchronization or should be avoided.
- Overusing static to "avoid creating objects." This drifts away from object-oriented design and makes code hard to test, because you cannot swap the behavior out. Keep object behavior in instance methods.
static finalfor constants — good;staticfor changing data — careful.static finalconstants likestatic final double PI = 3.14159;are perfectly idiomatic. A plain mutablestaticfield is the one to think twice about.
Where static fits in the bigger picture
static is your first taste of the difference between class-level and object-level thinking, which underpins a lot of Java design. Once you are comfortable here, look at constructors to see how instance state gets initialized, and revisit variables to compare the scopes and lifetimes of local, instance, and static variables side by side.
If you want mentor-led practice untangling static, instance, and initialization order — the exact stuff that turns into interview questions — that is built into the fundamentals module of the Java Full Stack course, and you can see how it connects to everything else in the Java learning hub.
Frequently Asked Questions
What is the difference between a static variable and an instance variable?
Why is the main method static in Java?
Can a static method access non-static variables?
When does a static block run?
Is it good practice to use static for everything?
Want to Build Your Career in Java Full Stack with AI?
Join CodeBegun and train with working industry engineers — Explore the Program

