Static nested classes in Java
Do not hold a reference to the outer instance.
new 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.
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());
}1234Compile error: code is privateCompile 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.
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
}
}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.
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
- new Outer.Nested() — no outer instance required
- Can't use outer instance fields directly
- Can access the outer class's private static members
- 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.
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());
}- 42
- 0
- Compile error: secret is private
- 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());
}- 3
- 0
- Compile error
- 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.