A static member belongs to the class and is shared among its instances.
So far, whenever we created an object (an instance), it had its own copy of the data.
If we create 100 Robot objects, we have 100 batteryLevel variables in memory. And that makes sense, because if Robot 1 uses battery, we don’t want Robot 2 to shut down.
But, what if we want to share a piece of data among ALL objects?
For example, we want to know the total number of robots manufactured. Or we want a universal constant like gravity (9.8). It doesn’t make sense to copy the value 9.8 into each of the 1,000 created objects. That would be an absurd waste of memory.
For this, the static modifier exists.
What does static mean?
When we mark an attribute or a method as static, it ceases to belong to the object (to the instance) and becomes part of the Class (the blueprint).
Static Variables (Class Attributes)
These are variables associated with the class and shared by its instances. There is one value per loaded class, a nuance that becomes relevant when multiple class loaders are involved.
The classic example: An instance counter.
public class Robot {
// Instance variable (Each robot has its own name)
private String name;
// STATIC variable (Shared by all robots)
// Used to count how many we have created
public static int robotCounter = 0;
public Robot(String name) {
this.name = name;
// Each time a robot is born, we increase the shared counter
robotCounter++;
}
}
How to access static members
Since they belong to the class, you don’t need an object to use them. They are accessed through the Class Name.
// No robots exist yet, but the variable already exists
System.out.println(Robot.robotCounter); // 0
Robot r1 = new Robot("Wall-E");
Robot r2 = new Robot("R2-D2");
// We access the shared variable
System.out.println(Robot.robotCounter); // 2
// NOTE: You can also access it from the object, but it's BAD PRACTICE
// System.out.println(r1.robotCounter); // Works, but is confusing.
Constants (static final)
If we combine static with final, we get a reference or value that can only be assigned once. If it points to a mutable object, final does not make that object immutable.
In Java, constants are written by convention in UPPERCASE_WITH_UNDERSCORES (Screaming Snake Case).
public class Physics {
// Public and global constant
public static final double GRAVITY = 9.81;
public static final double PI = 3.1415926535;
}
Usage:
double force = mass * Physics.GRAVITY;
// Physics.GRAVITY = 10.0; // ERROR! It's final, cannot be modified.
Java’s Math class is full of such constants, like Math.PI or Math.E.
Static Methods (Utility Methods)
A static method is a function that does not need an object to work. It does not depend on the internal state (variables) of any specific instance.
These are “tool” or utility methods.
- Example:
Math.sqrt(25). You don’t need to create aMathobject (new Math()) to calculate a square root. You simply use the tool.
public class Calculator {
// Static method: Receives everything it needs as parameters
public static int add(int a, int b) {
return a + b;
}
}
// Usage:
int result = Calculator.add(5, 5);
The Golden Rule
A static method CANNOT use this.
Why? Because this refers to the “current object”, and a static method can be executed without any object existing.
public class Robot {
private String name; // Instance
public static void info() {
// System.out.println(this.name); // FATAL ERROR!
// The static method doesn't know which robot you're talking about.
// It has no access to instance variables.
System.out.println("I am the Robot class."); // This is fine
}
}
Why is main static?
Now the famous line makes sense:
public static void main(String[] args)
It is static because, when the program starts, no object exists yet. The JVM needs an entry point that can be called “from nothing”, without having to do new Program().
When to use statics
- Global counters.
- Constants (
Math.PI). - Pure utility methods (
Math.max, unit converters). - The
mainmethod.
And don’t use them for everything else 😊.