Logically grouped with outer; no outer-instance needed
Non-static inner class
class Foo inside a class
Yes
Tightly coupled to outer instance; rare in modern Java
Local class
class Foo inside a method
Yes (if non-static method)
One-off implementation local to a block
Anonymous class
new Interface() { ... }
Yes (if non-static context)
Single-use; largely replaced by lambdas in Java 8+
Memory Model
Static Nested Class Inner (Non-static) Class
─────────────────── ────────────────────────
OuterClass OuterClass instance
├─ static fields ├─ fields
└─ NestedClass (static) └─ InnerClass (non-static)
no link back to outer hidden field: outer$this
can access outer.privateField
The Four Kinds
classOuter{// 1. Static nested - no outer instance neededstaticclassStaticNested{}// 2. Inner (non-static) - carries a reference to Outer.thisclassInner{voidhi(){System.out.println(outerField);}}// 3. Local class - defined inside a method bodyvoidmethod(){classLocalimplementsRunnable{publicvoidrun(){System.out.println("local");}}newLocal().run();}// 4. Anonymous class - instantiated inline, no nameRunnabler=newRunnable(){publicvoidrun(){System.out.println("anon");}};}
When Lambda Replaces Anonymous Class
Anonymous class is REQUIRED when: Lambda is PREFERRED when:
• Implementing an interface with • Exactly one abstract method
multiple abstract methods • No need to store state in fields
• Need to hold multiple fields • No need for super/this reference
• Need to call super • Conciseness matters
• Need to reference 'this' (the anon obj)
// Pre-Java 8 - anonymous class
Collections.sort(list, new Comparator<String>() {
public int compare(String a, String b) { return a.compareTo(b); }
});
// Java 8+ - lambda (Comparator is @FunctionalInterface)
list.sort(String::compareTo);