Difficulty: Intermediate
Explain the static keyword in Java. What are static variables, methods, blocks and nested classes, and what are their restrictions?
The static keyword says: this member belongs to the class itself, not to any particular object. Let me explain how that plays out in memory and in code, because that mental model explains all the restrictions.
Think of a school. Each student has their own roll number and marks (instance state), but the school name and the total number of enrolled students belong to the school, not to any student (static state). One copy is shared by everyone, and you can read it even before the first student joins.
Static variables have exactly one copy per class, stored in the class's memory area rather than inside each object. They are initialised when the class is loaded and are typically used for counters, constants (with final), and caches. Every object sees the same value, so changing it through one object changes it for all, and access through the class name, Counter.count, is the recommended style.
Static methods are called without an object. They can only directly use other static members, because there is no this. They cannot be overridden, only hidden, and they cannot be abstract. Utility methods such as Math.max and Collections.sort, and the main method itself, are static, and main has to be static because the JVM calls it before any object exists.
Static blocks are initialisers that run once, when the class is first loaded and initialised, before any object is created or any static method is called. They are useful for complex initialisation of static fields, like loading a driver or building a lookup table. Instance initialiser blocks, written with plain braces, run for every object, just before the constructor body.
Static nested classes are classes declared static inside another class. Unlike inner (non-static) classes, they do not carry a hidden reference to an outer instance, so they can be created without one and they are lighter. Builders, entries in maps, and helper types are commonly static nested. Note that a top-level class cannot be static.
The initialisation order is a frequent output question: static blocks and static field initialisers run in textual order when the class is first used, then for each new object, instance initialisers and field initialisers run in textual order, then the constructor body. In the example, class Counter is not loaded until the first new Counter(), so main start is printed before static block.
Watch out for common pitfalls. A static counter used from several threads needs synchronisation or an AtomicInteger. Static state makes testing hard because it leaks between tests, so use it sparingly. And a static reference to a large object can prevent garbage collection since it lives as long as the class is loaded, causing memory leaks.
In Python, class attributes and staticmethod or classmethod play a similar role, and in C++ static members must be defined outside the class for non-const data.
class Counter {
static int count;
int id;
static { System.out.println("static block"); }
{ System.out.println("instance block"); }
Counter() { id = ++count; }
static int total() { return count; }
}
public class StaticDemo {
public static void main(String[] args) {
System.out.println("main start");
new Counter();
new Counter();
System.out.println(Counter.total());
}
}
The static block runs once when Counter is first used; the instance block runs for each object.
static, class-loading, initialization-order, static-nested