Home/Learn/Java A–Z/Inner and Nested Classes

Inner and Nested Classes

Intermediate
OOP Deep Dive

Java 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.

StaticNested.java
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.

InnerClass.java
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.

AnonymousLocal.java
// 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 Aria
1

What is the difference between a static nested class and an inner class?

MediumAmazon
2

Why can inner classes cause memory leaks in Android?

HardGoogle
3

When would you still use an anonymous class instead of a lambda?

MediumOracle
4

What does "effectively final" mean for variables captured by a lambda or local class?

MediumMicrosoft
5

How do you access the enclosing instance from an inner class?

EasyTCS

Ask Aria about Inner and Nested Classes

Your personal AI tutor — ask anything about this concept