skip to content

Inside a lambda, what does the `this` reference point to, and how does that differ from `this` inside an anonymous inner class?

level: middleimportance: must knowfreq 65%

answer

  1. Lambda 'this' = enclosing instance (lexical)
  2. Anon class 'this' = the anonymous object
  3. Escape anon class with Outer.this
  4. Lambda can't reference itself via this
  5. Captured this keeps outer object alive (leak risk)

basics

~10 s

In 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 s

Lambdas 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 lines
java
class 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

for a junior

Knows the bottom line: lambda this is the outer object; anonymous-class this is the anonymous object.

for a middle

Explains lexical scoping, that bare member names resolve to the enclosing class, and how Outer.this reaches the outer object from an anonymous class.

for a senior

Adds the consequences: no name shadowing in lambdas, no self-reference via this, and that capturing this keeps the enclosing object alive.

for a principal

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).

context