Skip to content

Inner and static nested classes

A class defined inside another class is a nested class.

Stage 1core1 min read

What are they?

A nested class is a class written inside another class. A nested class without static is called an inner class.

Nesting tells the reader that the two classes belong together. A second question is whether each nested object is tied to one outer object. The word static answers that.

Two common cases:

  1. Inner class (no static). It belongs to one instance of the outer class and can use that outer object’s fields. You need an outer object to create it: outer.new Inner().
  2. Static nested class (declared with static). It does not belong to an instance. It is only grouped with the outer class to keep code tidy. You create it without an outer object: OuterClass.NestedClass obj = new OuterClass.NestedClass(...).

When to use static nested

  • When the nested class does not need the outer object (it never reads the outer’s non-static fields).
  • When you want a singleton holder. The holder class is loaded once, so the one instance inside it is created once. Or when you want a builder that constructs the outer class.

Example: static nested class (Builder)

public class BurgerMeal {
    private final String breadType;
    private final String patty;

    private BurgerMeal(BurgerMealWithBuilder builder) {
        this.breadType = builder.breadType;
        this.patty = builder.patty;
    }

    // Static nested: no outer instance needed. Name suggests it builds BurgerMeal.
    public static class BurgerMealWithBuilder {
        private String breadType;
        private String patty;

        public BurgerMealWithBuilder(String breadType, String patty) {
            this.breadType = breadType;
            this.patty = patty;
        }

        public BurgerMealWithBuilder withCheese(boolean add) {
            // ...
            return this;
        }

        public BurgerMeal build() {
            return new BurgerMeal(this);  // Allowed: a nested class can use its outer class's private members
        }
    }
}

// Usage: new BurgerMeal.BurgerMealWithBuilder("wheat", "chicken").withCheese(true).build()
  • BurgerMealWithBuilder is static, so you can create it without a BurgerMeal object: new BurgerMeal.BurgerMealWithBuilder(...). This matters because the BurgerMeal does not exist yet. The builder makes it.
  • BurgerMeal’s constructor is private, so outside code cannot call it. Only the builder’s build() creates a BurgerMeal.

Example: static nested class (Singleton holder)

public class JudgeAnalytics {
    private JudgeAnalytics() {}

    // Holder: loaded only when first used; JVM guarantees thread-safe initialization
    private static class JudgeAnalyticsHolder {
        private static final JudgeAnalytics INSTANCE = new JudgeAnalytics();
    }

    public static JudgeAnalytics getInstance() {
        return JudgeAnalyticsHolder.INSTANCE;
    }
}
  • The holder is a static nested class. It exists only to hold the single JudgeAnalytics instance. The holder is not loaded until getInstance() first uses it, so the instance is created lazily (only when first needed). Other code never names JudgeAnalyticsHolder; it only calls getInstance().

Where you see it in this repo

  • BuilderPattern/After: BurgerMeal.BurgerMealWithBuilder is the static nested builder.
  • SingletonDesignPattern/After: JudgeAnalytics.JudgeAnalyticsHolder is the static nested holder for the singleton instance.

In this topic

Done with this topic?

How well do you know it?

PreviousCloneable and clone()