Skip to main content

The static Keyword: Class vs. Instance Memory & Method Hiding

Medium

Interview Question: "What does the 'static' keyword actually mean, where are static members stored in memory, and why can't you override a static method? Also, why should you prefer static nested classes over inner classes?"

Every normal field and method in a class belongs to one object. Each object gets its own copy. static breaks that rule: a static member belongs to the class itself, not to any one object. There's only one copy, shared by every instance, loaded once when the class is loaded.

Think of a school: each student has their own name and marks (instance data). But the school's name is one value, shared by every student - that's the static field.

Student ClassMETHOD AREAstatic schoolName = "Harvard"SHARED REFERENCE (ONE COPY)Student Aname="Alice", marks=95Student Bname="Bob", marks=88Student Cname="Charlie", marks=91MUTATING schoolName THROUGH ANY INSTANCE UPDATES IT FOR ALL INSTANCES SIMULTANEOUSLY
Each student instance holds its own individual fields in heap memory. There is only one schoolName stored at the class level: every instance points at the same shared copy.

The quick answer​

The static keyword means a member belongs to the class, not an object. All instances share the exact same copy. You call it through the class name (ClassName.doSomething()), not through an object.

Static vs. instance members​

Instance MemberStatic Member
Belongs toOne specific objectThe class itself
Called asobject.doSomething()ClassName.doSomething()
Can accessBoth instance and static fieldsOnly static fields - no this
ResolvedAt runtime, based on the real objectAt compile-time, based on the declared type

Where does static actually live in memory?​

This trips people up because the answer changed across Java versions:

  • Java 7 and earlier: static variables and class metadata lived in PermGen, a region of the JVM heap.
  • Java 8+: PermGen was removed. Class metadata and bytecode now live in Metaspace, which sits in native memory, outside the heap.
  • The catch: the static variables themselves (and the Class object) still live on the regular Java heap, and can be garbage collected if their class loader is unloaded.

Can you override a static method?​

No. This is the one answer to memorize.

Overriding depends on the runtime looking at the real object and picking the right method - that's late binding. Static methods skip all of that: the compiler locks in which method gets called based on the declared type of the variable, before the program even runs. That's early binding, and it happens whether or not an object exists.

So if a subclass defines a static method with the same signature as the parent's, it doesn't override anything - it just hides it:

Parent p = new Child();
p.printRules(); // Prints "Parent Rules" - because p is declared as Parent, and static calls don't look at the real object

Static nested class vs. inner class​

Joshua Bloch's Effective Java says: "favor static member classes over non-static." Here's why that matters.

A regular (non-static) inner class secretly keeps a hidden reference back to the outer object that created it. If that inner object outlives the outer one - say it's sitting in a background thread or an event queue - the outer object can never be garbage collected. That's a memory leak hiding in plain sight.

A static nested class holds no such reference. It behaves like any ordinary top-level class: no hidden link, no leak risk.


Clean Code Example​

Here is how static variables, methods, and blocks are declared across languages:

public class Bank {
// 1. Static Variable: Shared by all bank accounts
public static double baseInterestRate;

// 2. Static Initializer Block: Runs once when class is loaded
static {
baseInterestRate = 0.045; // 4.5%
}

// 3. Static Utility Method: No access to instance state
public static double calculateInterest(double principal) {
return principal * baseInterestRate;
}

// 4. Static Nested Class: Does not leak outer instance reference
public static class TransactionLog {
public void log(String message) {
System.out.println("Log: " + message);
}
}
}