Inner and Nested Classes
IntermediateJava supports four types of nested classes — static nested, inner, local, and anonymous — each with different scoping and access rules.
Overview
Nested classes in Java are classes defined within another class or method. There are four kinds: static nested classes (like independent classes but namespaced), inner classes (non-static, hold a reference to the enclosing instance), local classes (defined inside a method), and anonymous classes (inline, one-time use). Understanding the difference between static nested and inner classes is a common interview topic, especially around memory and lifetime management.
Static Nested Classes
A static nested class is associated with its enclosing class name but does not hold a reference to an enclosing instance. It can access static members of the enclosing class but not instance members.
Static nested classes are used for helper types (Builder pattern), utility groups, and to avoid polluting the outer namespace.
public class Outer {
private static int staticField = 10;
private int instanceField = 20;
// Static nested — no reference to Outer instance
public static class Builder {
private String name;
private int age;
public Builder name(String name) {
this.name = name; return this;
}
public Builder age(int age) {
this.age = age; return this;
}
public Person build() {
return new Person(name, age);
}
// Can access outer static members
void show() { System.out.println(staticField); }
// void bad() { System.out.println(instanceField); } // ERROR
}
}
// Instantiate without an Outer instance
Outer.Builder b = new Outer.Builder().name("Alice").age(30);Inner Classes
A non-static inner class implicitly holds a reference to its enclosing class instance. It can access all members (including private) of the enclosing instance.
This hidden reference prevents the enclosing instance from being garbage-collected as long as the inner instance is live — a common memory leak source. Prefer static nested classes unless you genuinely need access to enclosing instance state.
public class LinkedList<T> {
private Node<T> head;
// Inner class — holds reference to LinkedList instance
private class ListIterator implements Iterator<T> {
private Node<T> current = head; // accesses outer field
@Override
public boolean hasNext() { return current != null; }
@Override
public T next() {
T val = current.data;
current = current.next;
return val;
}
}
public Iterator<T> iterator() {
return new ListIterator(); // requires enclosing instance
}
}Anonymous Classes and Local Classes
Anonymous classes are inline, one-shot implementations of an interface or abstract class — common before lambdas. They are still useful when you need a class with state (multiple methods) rather than a single functional interface.
Local classes are defined inside a method body and can capture effectively-final variables from the enclosing scope.
// Anonymous class (pre-lambda style)
Runnable r = new Runnable() {
private int count = 0;
@Override
public void run() {
count++;
System.out.println("Run #" + count);
}
};
// For single-method interfaces, prefer lambda
Runnable r2 = () -> System.out.println("Simple run");
// Local class — defined inside a method
void process(List<String> items) {
final String prefix = "Item: "; // effectively final
class Printer {
void print(String s) {
System.out.println(prefix + s); // captures local var
}
}
Printer p = new Printer();
items.forEach(p::print);
}Key Points to Remember
- Static nested class: no enclosing instance reference; use for Builder, helper types.
- Inner class: implicitly holds enclosing instance reference; can cause memory leaks.
- Anonymous class: one-shot inline implementation; prefer lambda for single-method interfaces.
- Local class: defined inside a method; captures effectively-final variables.
- To create an inner class instance from outside: outer.new Inner().
Practice Inner and Nested Classes in the Playground
Run and modify code directly in your browser - no setup needed.
Interview Questions
Sign in to ask AriaWhat is the difference between a static nested class and an inner class?
Why can inner classes cause memory leaks in Android?
When would you still use an anonymous class instead of a lambda?
What does "effectively final" mean for variables captured by a lambda or local class?
How do you access the enclosing instance from an inner class?
Ask Aria about Inner and Nested Classes
Your personal AI tutor — ask anything about this concept