In a Java lambda versus an anonymous inner class, what does the `this` keyword refer to, and why does it differ?
answer
- Lambda = no new scope; this = enclosing object
- Anonymous class = new object; this = the instance itself
- Reach outer from anon class: Outer.this
- Lambda is lexically scoped (behaves like inline code)
- Lambda params can't shadow enclosing locals
basics
~20 sIn 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 sA 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
Knows that this behaves differently and that a lambda's this is the surrounding object, even if unsure why.
Explains lexical scoping: lambda introduces no new this scope, anonymous class is its own object reached as Outer.this.
Connects scoping to name resolution and shadowing rules, and can name real callback bugs that the difference causes.
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