skip to content

Lambda vs Anonymous Class

Beyond syntax: lambdas produce no extra class file, do not shadow the enclosing scope, and are wired up at runtime through invokedynamic and LambdaMetafactory rather than compiled to an inner class. Interviewers use this to see whether you know a lambda is not just sugar for an anonymous class.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

4

In a Java lambda versus an anonymous inner class, what does the `this` keyword refer to, and why does it differ?

level: middleimportance: must knowfreq 78%

answer

  1. Lambda = no new scope; this = enclosing object
  2. Anonymous class = new object; this = the instance itself
  3. Reach outer from anon class: Outer.this
  4. Lambda is lexically scoped (behaves like inline code)
  5. Lambda params can't shadow enclosing locals

basics

~20 s

In a lambda, this means the enclosing object (the class where the lambda is written). In an anonymous class, this means the anonymous class instance itself. The lambda does not create a new scope for this.

solid answer

~40 s

A lambda does not introduce a new scope, so inside it `this` refers to the enclosing instance — the object of the class where the lambda appears — and you can call its methods and fields directly. An anonymous inner class, by contrast, is its own class, so `this` refers to that anonymous instance; to reach the outer object you must write `Outer.this`. The same applies to field and method name resolution: a lambda resolves names against the enclosing scope, while an anonymous class can declare its own members that shadow the outer ones. This is why lambdas are described as 'lexically scoped' — they behave like a piece of code embedded in the surrounding method rather than a separate object with its own identity.

go deeper

for a junior

Knows that this behaves differently and that a lambda's this is the surrounding object, even if unsure why.

for a middle

Explains lexical scoping: lambda introduces no new this scope, anonymous class is its own object reached as Outer.this.

for a senior

Connects scoping to name resolution and shadowing rules, and can name real callback bugs that the difference causes.

for a principal

Frames it via the JLS treatment of lambda bodies as enclosing-scope code and can reason about implications for refactoring anonymous classes to lambdas safely.

## Terms first - **Lambda expression**: a compact way to write an instance of a *functional interface* (an interface with one abstract method), e.g. `Runnable r = () -> System.out.println("hi");`. - **Anonymous inner class**: a class with no name, declared and instantiated in one expression, e.g. `Runnable r = new Runnable() { public void run() { System.out.println("hi"); } };`. - **`this` keyword**: a reference to 'the current object'. Which object that is depends on *what scope* the code belongs to. - **Lexical (static) scoping**: name meaning is decided by *where the code is written* in the source, not by what object is running it. ## The core difference An **anonymous class creates a brand-new class and a brand-new object**. That object has its own identity, so `this` inside it points to *that anonymous instance*. If the anonymous class is defined inside a class `Outer`, and you want the surrounding `Outer` object, you must write the *qualified* form `Outer.this`. A **lambda does NOT create a new scope for `this`**. The Java Language Specification treats the body of a lambda as if it were just more code in the enclosing method. So `this`, `super`, field names, and method names inside a lambda mean exactly what they would mean *on the line just before the lambda*. There is no separate lambda object whose `this` you could grab. ```java class Outer { Runnable lambda = () -> System.out.println(this); // 'this' = the Outer instance Runnable anonymous = new Runnable() { public void run() { System.out.println(this); } // 'this' = the anonymous instance // to reach Outer here you'd write Outer.this }; } ``` ## Why it matters in practice 1. **Calling enclosing methods**: inside a lambda you can call `someEnclosingMethod()` directly and it resolves to the outer class — no qualification. Inside an anonymous class, an unqualified call could accidentally bind to a method the anonymous class itself declares. 2. **Name shadowing**: an anonymous class may declare a local variable or parameter named the same as an enclosing field and *shadow* it; a lambda's parameters must NOT clash with local variables already in scope (the compiler rejects it), precisely because the lambda shares the enclosing scope rather than opening a fresh one. 3. **Listeners / callbacks**: a common bug is writing `this` inside an anonymous `ActionListener` expecting the enclosing component but getting the listener object instead. Converting it to a lambda 'just works' because `this` now means the enclosing object. ## Summary mental model - Anonymous class = *a new object* → `this` is the new object; reach outer with `Outer.this`. - Lambda = *inline code spliced into the method* → `this` is the enclosing object; no new scope, no shadowing of the enclosing scope.

  • How would you reference the enclosing instance from inside an anonymous class?
    Use the qualified form `Outer.this`, where `Outer` is the name of the enclosing class. Plain `this` refers to the anonymous instance.
  • Why does the compiler reject a lambda parameter named the same as a local variable in the enclosing method?
    Because a lambda shares the enclosing lexical scope rather than opening a new one, so the parameter and the local would collide in the same scope — that is a duplicate-variable error, not shadowing.

saying these in an interview costs you the question

  • Claiming `this` in a lambda refers to the lambda 'object' — there is no separate lambda object for `this`
  • Saying anonymous-class `this` reaches the enclosing instance directly (it needs `Outer.this`)
  • Believing lambdas can shadow enclosing local variables like anonymous classes can

context

open as a page

When should you prefer a lambda over an anonymous inner class in Java, and when must you fall back to an anonymous class?

level: juniorimportance: should knowfreq 62%

basics

~20 s

Use a lambda when implementing a functional interface (one abstract method) — it is shorter and clearer. Use an anonymous class when you need state (fields), multiple methods, a constructor, or to implement an interface/class with more than one method.

open as a page

How is a Java lambda compiled and instantiated at runtime, and how does that differ from an anonymous class?

level: seniorimportance: should knowfreq 55%

basics

~20 s

An anonymous class becomes its own .class file created at compile time. A lambda does not — the compiler emits an invokedynamic instruction, and at first run a bootstrap method (LambdaMetafactory) builds the implementation class on the fly.

open as a page

What runtime and startup trade-offs does the `invokedynamic`-based lambda implementation introduce, and how might a principal engineer reason about them at scale?

level: principalimportance: nice to knowfreq 28%

basics

~20 s

Lambdas avoid a class file per lambda, but the first time each lambda runs it pays a one-time linkage cost (the bootstrap synthesizes a class). For huge apps this first-call cost can add up at startup; tools like AppCDS or AOT linking can mitigate it.

open as a page