🪆 Enums, Records & Nested Types · Intermediate

Static nested classes in Java

Do not hold a reference to the outer instance.

🧩 The mysterynew Pizza.Builder() — a class inside a class, created without any Pizza existing yet. What's the relationship between them?

A class with a namespace

A static nested class is declared with static inside another class. It's an ordinary class, just namespaced by the outer one. It holds no reference to an outer instance, so you create it with new Outer.Nested() — no Outer object needed.

class Pizza {
    static class Builder {
        Pizza build() { return new Pizza(); }
    }
}
var p = new Pizza.Builder().build();

Private access, static only

Because it's a member of the outer class, the nested class can read the outer's private static members. Like any member, it can be private, hiding it as an implementation detail. What it can't touch: the outer's instance fields — there's no outer object to read them from.

🔮 Predict it

Peeking at a secret

code is private. What prints?

class Vault {
    private static String code = "1234";
    static class Clerk {
        String peek() { return code; }
    }
}
void main() {
    System.out.println(new Vault.Clerk().peek());
}
  1. 1234
  2. Compile error: code is private
  3. Compile error: needs a Vault object
Show the answer

Clerk is a member of Vault, so it shares Vault's private access. And as a static nested class it needs no Vault object at all.

⚠️ The trap

Reaching for instance fields

size belongs to each Outer object. A static nested class has no Outer object, so reading size is a compile error — not a zero, not a null.

class Outer {
    int size = 3;
    static class Nested {
        int get() { return size; }  // error
    }
}
🤔 Think first

Why static?

Builders and Map.Entry implementations are almost always *static* nested classes. Why?

Think about it, then reveal the answer

They don't need the outer object. A non-static (inner) class carries a hidden pointer to its outer instance; making it static avoids that extra reference — saving memory and preventing leaks. Rule of thumb: if it doesn't need the outer object, make it static.

💼 In the real world

Inside the JDK

HashMap stores entries in a static nested class called Node, and the Builder pattern (new Request.Builder().url(...).build()) is everywhere in HTTP clients. Static nesting keeps helper types close to their owner without extra baggage.

Key takeaways

  1. new Outer.Nested() — no outer instance required
  2. Can't use outer instance fields directly
  3. Can access the outer class's private static members
  4. Rule of thumb: if it doesn't need the outer object, make it static

💡 A spare key kept in the house's key box: it belongs to the house, but you don't need anyone home to use it.

🤯 Did you know?

The JVM has no idea classes can nest. javac compiles Pizza.Builder into its own file, Pizza$Builder.class, sitting next to Pizza.class.

Practice questions

What does this print?

class Outer {
    private static int secret = 42;
    static class Nested {
        int peek() { return secret; }
    }
}
void main() {
    var n = new Outer.Nested();
    System.out.println(n.peek());
}
  1. 42
  2. 0
  3. Compile error: secret is private
  4. Compile error: needs an Outer instance
Check your answer

42. Nested is a member of Outer, so it can read Outer's private static field, and as a static nested class it needs no Outer object.

What does this print?

class Outer {
    int size = 3;
    static class Nested {
        int get() { return size; }
    }
}
void main() {
    System.out.println(new Outer.Nested().get());
}
  1. 3
  2. 0
  3. Compile error
  4. Throws NullPointerException
Check your answer

Compile error. size is an instance field, but a static nested class has no Outer instance to read it from, so the compiler rejects it.

Next: drop the static and the nested class secretly grabs a pointer to its outer object — the root of a classic memory leak.