1. Static nested class
Static nested class (static nested class) is a class declared inside another class with the static modifier. In essence, it is a regular class that simply “lives” inside another class but is not tied to its instance.
If an inner class is like a younger sibling who always holds the older sibling’s hand (an instance of the outer class), then a static nested class is a cousin who only shows up for family holidays and otherwise lives their own life.
Key differences:
- Has no implicit reference to the outer class instance—no OuterClass.this and no access to non-static members.
- Can contain static members (unlike a regular inner class).
- Is instantiated without an instance of the outer class.
Declaration syntax
Declaring a static nested class is straightforward: use the static keyword inside the outer class.
class Outer {
static class Nested {
void print() {
System.out.println("Hello from Nested!");
}
}
}
That’s it! No tricky syntax—just static class.
Visualization:
Outer (outer class)
│
├── Nested (static nested class)
│ └── print()
2. Instantiating a static nested class
The nice part: you don’t need an instance of the outer class!
Outer.Nested nested = new Outer.Nested();
nested.print(); // Hello from Nested!
Note: we use the fully qualified name—Outer.Nested. It’s like referring to a nested class via the family name: “Smith.Son.”
Compare with an inner class:
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner(); // an outer object is required
And for a static nested class, an Outer instance isn’t needed at all!
3. Access to members of the outer class
This is where the main difference from an inner class lies.
- A static nested class has access ONLY to static members of the outer class.
- It cannot access non-static fields and methods (even if they are public).
Example:
class Outer {
private static int staticValue = 10;
private int instanceValue = 20;
static class Nested {
void show() {
System.out.println("Static value: " + staticValue); // OK
// System.out.println("Instance value: " + instanceValue); // Error!
}
}
}
If you try to access the non-static field instanceValue, the compiler will immediately give you a little lecture.
Why so? Because a static nested class doesn’t “know” which Outer instance to bind to—it has no reference to the outer class instance.
4. When to use static nested classes
When are they appropriate?
- When the nested class is logically related to the outer class but does not require access to the outer class instance.
- When you want to encapsulate a helper structure: for example, a builder, a utility, an enum, or even a small immutable object.
- When you need to reduce package clutter: the class is only needed by the outer class, so there’s no point extracting it.
Typical scenarios:
- The Builder pattern (especially for immutable objects)
- Implementing helper structures: for example, internal Node classes in collections
- Grouping constants or utilities
A simple rule of thumb
Ask yourself: “Does my nested class need access to a specific instance of the outer class?”
NO → use a static class (static nested)
YES → use a regular class (inner)
5. Usage examples
Example 1: A Builder for a class
Suppose we have a Person class and want to implement the Builder pattern for it:
public class Person {
private final String name;
private final int age;
// Private constructor
private Person(Builder builder) {
this.name = builder.name;
this.age = builder.age;
}
// Static nested Builder class
public static class Builder {
private String name;
private int age;
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setAge(int age) {
this.age = age;
return this;
}
public Person build() {
return new Person(this);
}
}
public void printInfo() {
System.out.println("Person: " + name + ", " + age);
}
}
Usage:
Person person = new Person.Builder()
.setName("Ivan")
.setAge(30)
.build();
person.printInfo(); // Person: Ivan, 30
Why is Builder a static nested class?
Because it doesn’t depend on a Person instance; it just helps create one. It is logically related to Person but not to any specific instance.
Example 2: A helper structure inside a collection
Imagine a “box of integers” class where a private static nested Node class is used to store elements:
public class IntBox {
private Node head;
// Nested static class
private static class Node {
int value;
Node next;
Node(int value) {
this.value = value;
}
}
public void add(int value) {
Node node = new Node(value);
node.next = head;
head = node;
}
public void printAll() {
Node current = head;
while (current != null) {
System.out.println(current.value);
current = current.next;
}
}
}
Usage:
IntBox box = new IntBox();
box.add(1);
box.add(2);
box.add(3);
box.printAll(); // 3 2 1
Why is Node static?
Because each Node doesn’t need to know about the entire box (IntBox); it simply stores the data and a reference to the next Node.
Example 3: A utility class inside a main class
public class MathUtils {
// Static nested class for working with complex numbers
public static class Complex {
private final double re;
private final double im;
public Complex(double re, double im) {
this.re = re;
this.im = im;
}
public Complex add(Complex other) {
return new Complex(this.re + other.re, this.im + other.im);
}
@Override
public String toString() {
return re + " + " + im + "i";
}
}
}
Usage:
MathUtils.Complex a = new MathUtils.Complex(1, 2);
MathUtils.Complex b = new MathUtils.Complex(3, 4);
MathUtils.Complex sum = a.add(b);
System.out.println(sum); // 4.0 + 6.0i
6. Useful nuances
Inner class vs. static nested class
| Inner class | Static nested class | |
|---|---|---|
| Keyword | none | |
| Implicit reference to the outer instance | yes | no |
| Access to non-static members of the outer class | yes | no |
| Access to static members of the outer class | yes | yes |
| May contain static members | no (constants only) | yes |
| Instantiation syntax | |
|
| Usage | When access to the outer instance is needed | When access to the outer instance is not needed |
Illustration
flowchart LR
OuterClass -->|has| InnerClass
OuterClass -.->|has| StaticNestedClass
StaticNestedClass -.->|can access| staticMembers
InnerClass -->|can access| instanceMembers
InnerClass -->|can access| staticMembers
Characteristics and limitations
- Static nested class can contain both instance and static fields and methods.
- It can be declared with any access modifier (public, private, protected, package-private).
- It can implement interfaces and extend other classes.
- It can be generic.
- It is commonly used to encapsulate internal helper classes that are not needed outside the outer class.
Example of a generic static nested class:
public class Box {
public static class Holder<T> {
private T value;
public Holder(T value) { this.value = value; }
public T get() { return value; }
}
}
When NOT to use a static nested class
- If the nested class needs access to the outer class’s non-static fields/methods—use a regular inner class.
- If the class is needed outside the outer class—extract it into a separate file.
- If the class is too large or complex—make it a top-level class.
7. Common mistakes and nuances
Error #1: Confusing an inner class and a static nested class.
Many beginners try to access non-static members of the outer class from a static nested class. But a static nested class has no reference to the outer class instance, so this is impossible. If you need access to the state of a specific object—use a regular inner class.
Error #2: Attempting to create a static nested class via an instance of the outer class.
There is no need to write outer.new Inner(). For a static nested class, always use new Outer.Nested().
Error #3: Using a static nested class for logic that requires access to the outer class instance.
If the class’s logic is tightly coupled to the state of the outer class’s instance, a static nested class is a poor choice. Use a regular inner class.
Error #4: Overly complex nesting.
Don’t overuse nested classes. If the structure becomes confusing, it’s better to extract some classes to top level.
GO TO FULL VERSION