skip to content

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