Skip to content
Java inner classes 5 min read

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 Outer object to create Outer.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 OuterAccessible from Nested?
static fields / methodsYes, directly
static private fieldsYes (nesting grants access)
Instance fields / methodsNo (without an Outer ref)
Instance private fieldsNo (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 DatabaseConfig immutable, hides the constructor, and groups the builder logic right next to the class it builds — all without polluting the top-level namespace.

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

FeatureStatic Nested ClassNon-Static Inner ClassTop-Level Class
Needs outer instance to createNoYesN/A
Can access outer instance fieldsNo (without ref)YesN/A
Can access outer static fieldsYesYesNo
Can declare static membersYesNo (Java < 16)Yes
Implicit reference to outerNoYesN/A

Note: Since Java 16, non-static inner classes are also allowed to declare static members. 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.class
  • Outer$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 .class files with javap -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, or Config).
  • 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 static fields 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.

  • 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 static means for fields, methods, and nested types
  • javap Tool — inspect compiled .class files to see how the compiler represents nested classes
Last updated June 13, 2026
Was this helpful?