Inside a lambda, what does the `this` reference point to, and how does that differ from `this` inside an anonymous inner class?
answer
- Lambda 'this' = enclosing instance (lexical)
- Anon class 'this' = the anonymous object
- Escape anon class with Outer.this
- Lambda can't reference itself via this
- Captured this keeps outer object alive (leak risk)
basics
~10 sIn a lambda, this means the same thing as in the code around it — the enclosing object. In an anonymous inner class, this means the anonymous object itself, not the surrounding one.
solid answer
~40 sLambdas do not introduce a new `this`. `this` inside a lambda is **lexically scoped**: it resolves to whatever `this` means in the enclosing method — the surrounding (outer) instance. Likewise, unqualified field and method names inside a lambda refer to the enclosing class's members, and there is no shadowing of `this`. An **anonymous inner class** behaves differently: it is itself a new object, so `this` inside it refers to that anonymous instance, and to reach the outer object you must write `Outer.this`. This makes lambdas cleaner for callbacks where you want the enclosing object, and it's why you can't use `this` inside a lambda to refer to the function object. It also means a lambda is not a separate scope for name resolution the way an anonymous class is.
code
java · 12 linesclass Outer {
int id = 1;
void run() {
Runnable lambda = () -> System.out.println(this.id); // this = Outer instance
Runnable anon = new Runnable() {
public void run() {
// System.out.println(this.id); // would NOT compile: anon has no 'id'
System.out.println(Outer.this.id); // must qualify to reach Outer
}
};
}
}go deeper
Knows the bottom line: lambda this is the outer object; anonymous-class this is the anonymous object.
Explains lexical scoping, that bare member names resolve to the enclosing class, and how Outer.this reaches the outer object from an anonymous class.
Adds the consequences: no name shadowing in lambdas, no self-reference via this, and that capturing this keeps the enclosing object alive.
Connects it to callback/API ergonomics (why lambdas reduced Outer.this boilerplate), recursion patterns, and lifecycle/leak management for long-lived handlers.
## Background terms - **`this`**: a reference, available inside an instance method, pointing to the object the method was called on (the 'current' object). - **Lexical scoping**: a name's meaning is determined by *where it is written in the source*, by looking outward through the enclosing code — not by what kind of construct contains it. - **Anonymous inner class**: an unnamed class defined and instantiated in one expression, e.g. `new Runnable() { public void run() { ... } }`. It creates a brand-new object of a new (anonymous) class. ## The core difference A lambda is **not a new scope for `this`**. When you write `this` inside a lambda, Java resolves it exactly as if you'd written it in the surrounding method: it is the **enclosing instance**. The same holds for bare member names: `field` inside a lambda means `this.field` of the *enclosing* object, and a bare method call `helper()` calls the enclosing class's method. An anonymous inner class **is** a new object. Inside its body, `this` refers to *that* anonymous object. To reach the surrounding object you must qualify: `Outer.this`. Bare names there resolve against the anonymous class first (it can shadow outer members). ## A concrete contrast ```java class Widget { String name = "widget"; Runnable asLambda() { return () -> System.out.println(this.name); // 'this' == the Widget -> "widget" } Runnable asAnon() { return new Runnable() { String name = "runnable"; public void run() { System.out.println(this.name); // 'this' == the anonymous Runnable -> "runnable" System.out.println(Widget.this.name); // reach the outer object -> "widget" } }; } } ``` `asLambda()` prints `widget`; `asAnon().run()` prints `runnable` then `widget`. ## Why lambdas were designed this way Lambdas are meant to be lightweight pieces of behavior, not objects you interact with. Capturing the enclosing `this` lexically removes a whole class of bugs and boilerplate: in pre-Java-8 callback code you constantly wrote `Outer.this.foo()` or saved `Outer self = this;` to escape the anonymous class's `this`. With lambdas you just write `foo()` and it means the enclosing method's `foo()`. The trade-off is that a lambda cannot refer to *itself* via `this` (it isn't a named object); recursion needs a field or a named method reference instead. ## Consequences and gotchas 1. **No shadowing**: a lambda parameter may not reuse the name of a variable in the enclosing scope (unlike an anonymous class, where members can shadow outer ones). The lambda shares the enclosing scope's names. 2. **Self-reference**: you can't capture a lambda in its own initializer to call itself; assign it to a field/local declared first, or use a method. 3. **Memory leaks**: because a non-static-context lambda or anonymous class captures the enclosing `this`, it keeps the outer object alive; long-lived listeners holding such a reference can leak. (A lambda that captures nothing — no `this`, no locals — is non-capturing and may be cached by the runtime.) ## Deriving your answer per level - Junior: 'lambda this = the surrounding object; anonymous class this = the anonymous object.' - Middle: add lexical scoping and `Outer.this` to escape the anonymous class. - Senior: add the no-shadowing and self-reference consequences and the leak implication. - Principal: discuss API/callback ergonomics and lifecycle/leak management.
- How do you write a recursive lambda given that it can't reference itself with `this`?Declare the field/variable first, then assign the lambda, so the lambda body can refer to that name: e.g. a field `Function<Integer,Integer> fact;` assigned `n -> n <= 1 ? 1 : n * fact.apply(n-1);`. A named method (method reference) is usually cleaner.
- Can a lambda inside a static method use `this`?No. A static method has no `this`, so a lambda written there has no enclosing instance to resolve `this` to — using `this` is a compile error, exactly as it would be directly in that static method.
A lambda is like a sticky note written in someone's notebook: 'me' on the note still means the notebook's owner. An anonymous class is like a new person standing in the room: 'me' now means that new person, and you must say 'the host' (Outer.this) to point back at the owner.
saying these in an interview costs you the question
- Saying `this` in a lambda refers to the lambda/function object — it refers to the enclosing instance.
- Claiming lambdas and anonymous classes are 'the same thing' for scoping — they differ precisely on `this`, shadowing, and being a new scope.
- Believing you can do `LambdaType.this` to reach the lambda — a lambda is not a named type/object.
- Forgetting that a lambda capturing `this` pins the enclosing object in memory (listener leak risk).