Static vs Non-Static in Java: Differences With Examples
A static member belongs to the class and is shared. A non-static member belongs to each object. See the difference in code, with the famous compiler error explained.

Say you write a Java class called Student. You add a field college and mark it static by accident. Now every student object shows the same college, and changing one changes all of them. The bug is one keyword long, and it is one of the most common mistakes in first-year Java.
The keyword static decides who owns a member of a class: the class itself, or each object made from it. This post shows the difference with code you can compile, then the rules that cause the famous compiler error.
A static member belongs to the class and exists once. A non-static member belongs to each object, so every object gets its own copy. You reach a static member with the class name, and a non-static member only through an object. That one rule explains almost every error message you will see about static.
Static vs non-static: side-by-side table
Read this table first. The sections below explain each row with code.
| Point | Static | Non-static (instance) |
|---|---|---|
| Belongs to | The class | Each object |
| Copies in memory | One, shared | One per object |
| How to call | ClassName.member | object.member |
| Needs an object? | No | Yes |
Can use this? | No | Yes |
| Can use the other kind directly? | Only static members | Both static and non-static |
| Typical use | Counters, constants, helper methods | Data that differs per object |
Static variable vs instance variable
Java stores a static variable once, with the class. It stores an instance variable inside each object, on the heap. The Oracle Java tutorial on class members uses a bicycle example for exactly this idea: gear and speed belong to each bicycle, while a count of bicycles belongs to the class.
Here is a small class that counts how many objects were created. The counter must be shared, so it is static. Each object's own count must be separate, so it is not.
public class Counter {
static int totalCreated = 0; // one copy, shared by all objects
int count = 0; // one copy per object
Counter() {
totalCreated++;
}
void increment() { // non-static method
count++;
}
static int getTotalCreated() { // static method
return totalCreated;
}
public static void main(String[] args) {
Counter a = new Counter();
Counter b = new Counter();
a.increment();
a.increment();
b.increment();
System.out.println(a.count); // 2
System.out.println(b.count); // 1
System.out.println(Counter.getTotalCreated()); // 2
}
}
Object a has a count of 2 and object b has a count of 1. Both objects see the same totalCreated, which is 2. This code compiles and prints exactly those three numbers.
Static method vs non-static method
You call a static method on the class itself, and main is the best-known case: the JVM must start your program before any object exists. The Java language specification describes this under class methods.
A non-static method needs an object, because it works on that object's data.
public class Utils {
static int square(int n) { return n * n; }
int cube(int n) { return n * n * n; }
public static void main(String[] args) {
System.out.println(Utils.square(4)); // 16, no object needed
System.out.println(new Utils().cube(3)); // 27, object needed
System.out.println(Math.max(3, 9)); // 9, a static method from the JDK
}
}
Math.max is a good example from the Java library. You never write new Math(), because a maximum does not depend on any object's data.
A useful test: look at the method body. If it reads or changes only its parameters, it can be static. If it reads this.name or any other field of the object, it cannot.
Can static methods access non-static variables?
No, and the reason is timing. The variable lives inside an object, and a static method may run before any object has been created.
This is the code that gives the famous error:
public class BadAccess {
int age = 20;
public static void main(String[] args) {
System.out.println(age);
}
}
The compiler stops with: non-static variable age cannot be referenced from a static context. Java is asking one question: which object's age do you mean? You have two fixes. Build an object and read the field through it, or move the field to the class by making it static.
public class StaticAccess {
int age = 20;
static String college = "DevHives College";
static void show() {
System.out.println(college); // OK: static uses static
StaticAccess s = new StaticAccess();
System.out.println(s.age); // OK: through an object
}
void print() {
System.out.println(age + " " + college); // OK: non-static can use both
}
public static void main(String[] args) {
show();
new StaticAccess().print();
}
}
The opposite direction always works. When an object exists, its class is already loaded, so the object's methods can read every static field.
Static block in Java
Java runs a static block one time, when it first loads the class. People use it for setup that must finish before anything else, such as filling a lookup table. The matching tool for objects is the instance initializer block, which runs before the constructor each time you create an object.
public class StaticBlock {
static int answer;
int id;
static {
System.out.println("static block runs once");
answer = 42;
}
{
System.out.println("instance block runs for every object");
id = 7;
}
StaticBlock() {
System.out.println("constructor runs");
}
public static void main(String[] args) {
System.out.println("main starts, answer = " + answer);
new StaticBlock();
new StaticBlock();
}
}
The output order is the lesson. The static block prints first, then main starts. After that, each new StaticBlock() prints the instance block line and then the constructor line, twice in total.
Class loads
Static variables get values and the static block executes.
Object is created
Instance variables get default values.
Instance block runs
Any
{ ... }block in the class body executes.Constructor runs
Your constructor finishes the setup.
Static class vs non-static class
Java allows the static keyword on a class only when the class sits inside another class. A top-level class cannot use the keyword. You can create a static nested class without any outer object. A non-static nested class (called an inner class) always belongs to an outer object.
public class Outer {
int x = 10;
static class StaticNested {
void hello() { System.out.println("no outer object needed"); }
}
class Inner {
void show() { System.out.println("x = " + x); } // can read the outer x
}
public static void main(String[] args) {
new StaticNested().hello();
Outer o = new Outer();
Outer.Inner in = o.new Inner();
in.show();
}
}
A nested class that never reads the outer object's fields should be static. Then it carries no hidden reference, so it cannot keep the outer object alive by accident.
Static final constants and static imports
The most common safe use of static is a constant. Add final so nobody can change the value, and name it in capital letters.
public class Config {
static final int MAX_LOGIN_TRIES = 3;
static final String APP_NAME = "DevHives Portal";
public static void main(String[] args) {
System.out.println(APP_NAME + " allows " + Config.MAX_LOGIN_TRIES + " tries");
}
}
One copy of each constant exists, so a thousand objects do not waste memory repeating it. Java also lets you write import static java.lang.Math.max; and then call max(3, 9) without the class name. Use that sparingly, because the reader can no longer see where max came from.
Static and threads
A shared static variable can be changed by several threads at once, and the result can be wrong. Say two threads both run totalCreated++ in the Counter class. The increment is really three steps: read, add, write. Two threads can read the same old value, so one update is lost.
For a counter that many threads touch, use AtomicInteger instead of a plain static int. For constants, no risk exists, because nobody changes them.
An interview question: can you override a static method?
No. If a child class declares a static method with the same signature, it hides the parent method instead of overriding it. Overriding works on objects at run time. Hiding is decided by the variable's declared type when the code is compiled.
class Parent {
static void who() { System.out.println("Parent"); }
}
class Child extends Parent {
static void who() { System.out.println("Child"); }
}
public class HideDemo {
public static void main(String[] args) {
Parent p = new Child();
p.who(); // prints Parent, because the declared type is Parent
Child.who(); // prints Child
}
}
Many interviewers also ask whether a constructor can be static (it cannot) and whether this works inside a static method (it does not). Both answers follow from the same rule: static has no current object.
When to use static, and when not to
Use static for
- Constants, such as
static final double PI - Helper methods that use only their parameters
- A counter or setting shared by every object
Avoid static for
- Data that is different for each object, like a student's name
- Anything you want to replace with a fake in a test
- Mutable shared state that many threads change
My own rule is simple: start every member as non-static. Make it static only when you can say, in one sentence, why all objects must share it. Beginners often reach for static to silence the compiler error above. That fixes the error and creates a design problem.
Common mistakes
- Calling a static method through an object.
obj.staticMethod()compiles, but it hides the fact that no object is used. WriteClassName.staticMethod(). - Using
thisin a static method. There is no current object, so the compiler rejects it. - Making a field static to fix an error. Every object then shares one value, which is the bug from the start of this post.
- Expecting a static method to be overridden. Static methods are hidden, not overridden. The method that runs depends on the variable's declared type.
What to do next
If you are still building your Java base, follow the free Java course syllabus first. Then open an editor and copy Counter from above. Add a second static variable and a second non-static variable, then print both from two objects. Predict each output before you run it. When your predictions match every time, you understand static. Push the file to a repository with a clear README, as shown in this GitHub README guide, so you have proof of practice.
