Skip to content
  • Inner, Nested, Local & Anonymous Classes · Java

Inner, Nested, Local & Anonymous Classes

LearnViaNotes @learnvianotes· 4 min read

A class can be declared inside another class, method or expression. The four kinds differ in one key way: whether they hold a hidden reference to an enclosing instance.

The four kinds at a glance

KindDeclaredOuter instance?Typical use
Static nestedstatic class Node inside a classNoHelpers that belong with the outer class: Map.Entry, Builder, linked-list Node
Inner (member)class Itr inside a classYes — Outer.thisIterators and views that need the outer object's fields
Localclass X inside a method bodyYes, if in an instance methodA one-method helper type with a name
Anonymousnew Interface() { … } expressionYes, if in an instance contextOne-off implementation; mostly replaced by lambdas

Static nested vs inner

Java
public class Main {
    private int size = 3;
    private static String kind = "outer";

    static class StaticNested {            // no outer instance
        String describe() { return "nested sees " + kind; }   // only static members
    }

    class Inner {                          // bound to a Main instance
        int size = 10;
        String describe() {
            return "inner " + size + ", outer " + Main.this.size;
        }
    }

    public static void main(String[] args) {
        StaticNested n = new StaticNested();          // no Main needed
        System.out.println(n.describe());

        Main outer = new Main();
        Main.Inner in = outer.new Inner();            // needs an outer instance
        System.out.println(in.describe());
    }
}
Output
nested sees outer
inner 10, outer 3

Local and anonymous classes

Java
import java.util.*;

public class Main {
    interface Greeter { String greet(String name); }

    public static void main(String[] args) {
        String greeting = "Hello";                  // effectively final → can be captured

        class Polite implements Greeter {           // local class: has a name, lives in this method
            public String greet(String name) { return greeting + ", " + name + "!"; }
        }

        Greeter shout = new Greeter() {             // anonymous class: no name, one instance
            @Override
            public String greet(String name) { return greeting.toUpperCase() + " " + name; }
        };

        Greeter lambda = name -> greeting + " " + name;   // same thing, as a lambda

        System.out.println(new Polite().greet("Asha"));
        System.out.println(shout.greet("Ravi"));
        System.out.println(lambda.greet("Mei"));

        List<String> names = new ArrayList<>(List.of("bob", "Al", "carol"));
        names.sort(new Comparator<String>() {       // classic pre-Java-8 style
            public int compare(String a, String b) { return a.length() - b.length(); }
        });
        System.out.println(names);
    }
}
Output
Hello, Asha!
HELLO Ravi
Hello Mei
[Al, bob, carol]

Capturing variables: effectively final

Local, anonymous classes and lambdas can read local variables of the enclosing method only if they are final or effectively final (never reassigned). The value is copied into the object, so allowing later changes would make the copy and the variable disagree.

Java
public class Main {
    public static void main(String[] args) {
        int count = 0;
        Runnable r = () -> System.out.println(count);
        count++;                 // makes count not effectively final
        r.run();
    }
}
Compiler error
Main.java:4: error: local variables referenced from a lambda expression must be final or effectively final
        Runnable r = () -> System.out.println(count);
                                              ^

Anonymous class vs lambda

Anonymous classLambda
ImplementsAny interface or abstract/concrete class, many methodsOnly a functional interface (one abstract method)
this meansThe anonymous object itselfThe enclosing instance
StateCan have fieldsNo fields of its own
Compiled toA separate Main$1.class fileinvokedynamic — no extra class file

Static nested vs inner class — when to use which?

Why must captured local variables be effectively final?

What does this refer to inside a lambda vs an anonymous class?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report