Static Nested Class
A static nested class is a class defined inside another class with the static modifier. Unlike a regular inner class, it does not hold a reference to an instance of the outer class — it behaves more like a top-level class that just happens to live inside another one for organizational purposes.
Syntax
You declare a static nested class the same way you declare any static member — just add static before the class keyword.
public class Outer {
private static int outerStaticField = 10;
private int outerInstanceField = 20;
static class Nested {
void display() {
// Can access static members of Outer directly
System.out.println("Outer static field: " + outerStaticField);
// Cannot access outerInstanceField — no Outer instance!
}
}
}
To instantiate the static nested class, you reference it through the outer class name — no outer instance required:
public class Main {
public static void main(String[] args) {
Outer.Nested nested = new Outer.Nested();
nested.display();
}
}
Output:
Outer static field: 10
Note: You never need an
Outerobject to createOuter.Nested. This is the key distinction from a non-static member inner class.
What a Static Nested Class Can and Cannot Access
This table summarises access rules at a glance:
Member in Outer | Accessible from Nested? |
|---|---|
static fields / methods | Yes, directly |
static private fields | Yes (nesting grants access) |
| Instance fields / methods | No (without an Outer ref) |
| Instance private fields | No (without an Outer ref) |
If you genuinely need to reach an instance member, you can pass an Outer reference explicitly:
public class Outer {
private int value = 42;
static class Nested {
void printValue(Outer outer) {
// Explicit reference — perfectly valid
System.out.println("Value: " + outer.value);
}
}
public static void main(String[] args) {
Outer o = new Outer();
Nested n = new Nested();
n.printValue(o);
}
}
Output:
Value: 42
A Real-World Example: Builder Pattern
The Builder pattern is one of the most common and idiomatic uses of static nested classes in Java. StringBuilder-style builders, HttpRequest.Builder, and many framework classes follow this exact structure.
public class DatabaseConfig {
private final String host;
private final int port;
private final String name;
private DatabaseConfig(Builder builder) {
this.host = builder.host;
this.port = builder.port;
this.name = builder.name;
}
@Override
public String toString() {
return host + ":" + port + "/" + name;
}
// Static nested Builder class
public static class Builder {
private String host = "localhost";
private int port = 5432;
private String name;
public Builder host(String host) {
this.host = host;
return this;
}
public Builder port(int port) {
this.port = port;
return this;
}
public Builder name(String name) {
this.name = name;
return this;
}
public DatabaseConfig build() {
if (name == null) throw new IllegalStateException("Database name required");
return new DatabaseConfig(this);
}
}
public static void main(String[] args) {
DatabaseConfig config = new DatabaseConfig.Builder()
.host("db.example.com")
.port(5432)
.name("myapp")
.build();
System.out.println(config);
}
}
Output:
db.example.com:5432/myapp
Tip: This pattern keeps
DatabaseConfigimmutable, hides the constructor, and groups the builder logic right next to the class it builds — all without polluting the top-level namespace.
Another Common Use: Grouping Related Helpers
Static nested classes are also great for grouping helper types that only make sense in the context of the outer class.
public class Graph {
private int vertices;
public Graph(int vertices) {
this.vertices = vertices;
}
// Edge only makes sense inside a Graph context
public static class Edge {
int from;
int to;
double weight;
public Edge(int from, int to, double weight) {
this.from = from;
this.to = to;
this.weight = weight;
}
@Override
public String toString() {
return from + " --(" + weight + ")--> " + to;
}
}
public static void main(String[] args) {
Graph.Edge e = new Graph.Edge(0, 3, 1.5);
System.out.println(e);
}
}
Output:
0 --(1.5)--> 3
Static Nested Class vs Inner Class vs Top-Level Class
| Feature | Static Nested Class | Non-Static Inner Class | Top-Level Class |
|---|---|---|---|
| Needs outer instance to create | No | Yes | N/A |
| Can access outer instance fields | No (without ref) | Yes | N/A |
| Can access outer static fields | Yes | Yes | No |
Can declare static members | Yes | No (Java < 16) | Yes |
| Implicit reference to outer | No | Yes | N/A |
Note: Since Java 16, non-static inner classes are also allowed to declare
staticmembers. Before Java 16 this was forbidden.
Under the Hood
The JVM does not have a concept of “nested” classes. When you compile Outer.java containing a static nested class, javac produces two separate .class files:
Outer.classOuter$Nested.class
The $ delimiter is a compiler convention. You can verify this yourself:
$ javac Outer.java
$ ls *.class
Outer.class Outer$Nested.class
Because Outer.Nested is compiled as a plain class with no synthetic reference to Outer, there is no hidden memory overhead per instance (unlike a non-static inner class, which stores a pointer back to its enclosing instance). This makes static nested classes preferable whenever you don’t need that outer-instance access.
Access to private static members of Outer is resolved at the compiler level by generating synthetic accessor methods (bridge methods) only in older compilers. From Java 11 onward, the JVM’s nest attribute (NestHost / NestMembers) allows truly private access between nesting companions without synthetic helpers, making it both cleaner and slightly more performant.
Tip: When you inspect
.classfiles withjavap -c Outer, you can see the nest attributes and verify there are no synthetic bridges in modern Java.
When to Use a Static Nested Class
Use a static nested class when:
- The nested class is logically tied to the outer class but doesn’t need access to its instance state (e.g., a
Builder,Entry, orConfig). - You want to keep a helper type out of the top-level namespace without making it a separate file.
- You’re implementing the Builder or Factory pattern inside a class.
- You need to declare
staticfields or methods inside the nested class (you can’t do this in a non-static inner class prior to Java 16).
Avoid a static nested class when the nested class genuinely needs to work on the outer instance’s data — in that case a non-static member inner class is the right tool.
Related Topics
- Member Inner Class — non-static inner classes that hold an implicit reference to their enclosing instance
- Anonymous Inner Class — one-off class definitions created inline, often replaced by lambdas
- Local Inner Class — classes defined inside a method body for very localised logic
- Inner Classes Overview — a bird’s-eye view of all four inner-class types
- static Keyword — deep dive into what
staticmeans for fields, methods, and nested types - javap Tool — inspect compiled
.classfiles to see how the compiler represents nested classes