Anonymous Inner Class vs Lambda in Java — Scoping, this, Bytecode, When to Use Each
Fast recall
Quick revision
Core answer
this (refers to the inner instance), can implement any interface or extend any class, and holds an implicit reference to the enclosing instance (memory-leak risk). Lambda compiles to a private synthetic method + `invokedynamic` via LambdaMetafactory, inherits this from the enclosing scope (no new this), works only on functional interfaces (single abstract method), and captures variables without allocating a new class unless needed. Use lambdas by default — smaller, faster, idiomatic. Use anonymous classes only when you need state, multiple methods, or to override methods of a concrete class.Whether the candidate understands the bytecode and runtime differences — not just syntax. Knows that `this` means different things in each, and that lambdas can only implement functional interfaces
Treating lambdas as 'just sugar' for anonymous classes. Thinking lambdas always allocate a new object per invocation. Confusing `this` inside a lambda with the lambda itself
Explain `invokedynamic` + `LambdaMetafactory` caching non-capturing lambdas as singletons. Mention that anonymous inner classes hold an implicit reference to the enclosing instance (classic Android memory leak). Show the `effectively final` capture rule
Interview-ready guide
Interview answer
They look similar but the JVM handles them through completely different mechanisms — lambdas are not just syntactic sugar for anonymous classes.
What the compiler produces
- Anonymous class: a separate
.classfile likeOuter$1.class; instantiated withnewevery time - Lambda: a private synthetic method + an
invokedynamiccall bootstrapped byLambdaMetafactoryat runtime; non-capturing lambdas are cached as singletons
`this` keyword
- Inside an anonymous class,
thisis the inner instance; you reach the outer viaEnclosingClass.this.field - Inside a lambda,
thisis the enclosing instance directly — no ceremony
What each can implement
- Anonymous class: any interface, abstract class, or concrete class with overridable methods
- Lambda: only functional interfaces — exactly one abstract method
State and methods
- Anonymous class can hold fields and override multiple methods
- Lambda has no fields; captures outer variables that must be
finalor effectively final; body is one method
Memory-leak risk
- Anonymous class always holds an implicit reference to the enclosing instance — classic Android/Swing leak pattern
- Lambda only captures the enclosing instance if it references
thisor an instance field; stateless lambdas don't leak the outer
When to use which
- Default to lambdas — smaller, faster for non-capturing cases, more idiomatic
- Reach for anonymous classes when you need to extend a concrete class, override multiple methods, or hold instance state inside the implementation
Recommendation: For Java 8+ code, use lambdas everywhere a functional interface fits, and prefer method references like String::trim over trivial x -> x.trim() lambdas. Reserve anonymous inner classes for the cases lambdas can't cover — extending a concrete class, overriding multiple methods, or needing internal state.
Anonymous Inner Class vs Lambda in Java — Scoping, `this`, Bytecode, When to Use Each
Direct Answer
Both let you implement a single-method interface inline, but they're different beasts. Anonymous inner class compiles to a new .class file, has its own this (refers to the inner instance), can implement any interface or extend any class, and holds an implicit reference to the enclosing instance (memory-leak risk). Lambda compiles to a private synthetic method + invokedynamic via LambdaMetafactory, inherits this from the enclosing scope (no new this), works only on functional interfaces (single abstract method), and captures variables without allocating a new class unless needed. Use lambdas by default — smaller, faster, idiomatic. Use anonymous classes only when you need state, multiple methods, or to override methods of a concrete class.
Common Mistakes & Pitfalls
Treating lambdas as 'just sugar' for anonymous classes. Thinking lambdas always allocate a new object per invocation. Confusing this inside a lambda with the lambda itself
Check your understanding
Answer these without looking back at the article.
- Why are non-capturing lambdas cached as singletons by the JVM but non-capturing anonymous classes are not?
- Explain `effectively final` — why can't a lambda capture a mutable local variable?
- What is `invokedynamic` and how does `LambdaMetafactory` use it to generate lambda implementations?
- Why do anonymous inner classes cause memory leaks in Android activities, and how do lambdas avoid this?
- Can a lambda replace an anonymous class that extends `Thread` or `TimerTask`? Why or why not?
Related interview prep categories
1Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.