Inside an anonymous class, what does `this` refer to, and how do you reach the enclosing instance? How does this differ from a lambda?
answer
- Anon/local `this` = the inner instance
- Enclosing instance = Outer.this (qualified this)
- Inner names can shadow outer names
- Lambda `this` = enclosing instance (lexical)
- Lambda can't self-reference via `this`
basics
~20 sInside an anonymous (or local) class, this means that inner object itself, not the enclosing object. To reach the enclosing instance you write Outer.this. A lambda is different: its this is the enclosing instance, because a lambda has no this of its own.
solid answer
~50 sAn anonymous or local class is a real class with its own instance, so `this` inside it refers to *that* inner instance. To access the surrounding object you qualify it: `EnclosingClassName.this`. This matters when names collide — an inner method or field can shadow an enclosing one, and `Outer.this.field` disambiguates. A lambda behaves oppositely: it does not introduce a new scope for `this`, so `this`, unqualified field names, and `super` all resolve to the *enclosing* instance exactly as they would in the surrounding method. That's a key practical difference: converting an anonymous `Runnable` whose body uses `this` into a lambda silently changes what `this` means, which can break code (e.g. registering/unregistering a listener that referenced itself via `this`). Anonymous classes also generate their own class file (Outer$1.class) and can shadow names; lambdas generate no such separate type and never shadow the enclosing `this`.
code
java · 12 linesclass Button {
private final List<Runnable> listeners = new ArrayList<>();
void addSelfRemovingListener() {
listeners.add(new Runnable() {
@Override public void run() {
System.out.println("fired");
listeners.remove(this); // `this` = this Runnable; removes itself. Works.
// As a lambda, `this` would be the Button, and remove(this) would be wrong.
}
});
}
}go deeper
Knows Outer.this reaches the outer object and that plain this is the inner object.
Explains shadowing and qualified this, and that a lambda's this is the enclosing instance.
Articulates the lexical-this rule for lambdas, the refactoring hazard, and self-reference limitations of lambdas; reads stack traces accordingly.
Sets guidance on when to keep anonymous/named classes vs lambdas for clarity, debuggability, and safe self-referential listener patterns across a codebase.
## `this` is about the *current object* `this` always means 'the object whose method is currently executing.' An anonymous class and a local class each define a **new class**, and when you call a method on an instance of that class, `this` inside the method is **that inner instance** — distinct from the object of the method that created it. ```java class Outer { int x = 10; Runnable make() { return new Runnable() { int x = 20; // shadows Outer.x @Override public void run() { System.out.println(x); // 20 -> the anonymous instance's field System.out.println(this.x); // 20 -> `this` is the anonymous instance System.out.println(Outer.this.x); // 10 -> the enclosing instance } }; } } ``` ## Reaching the enclosing instance: `Outer.this` A non-static local or anonymous class holds a hidden reference to the **enclosing instance** (the object whose method created it). You access it with the **qualified this** syntax `EnclosingClassName.this`. This is necessary whenever a name inside the inner class **shadows** (hides) an enclosing name, or whenever you simply want to pass the outer object somewhere (`someApi.register(Outer.this)`). ## Shadowing Because the inner class is its own scope, a field or method declared inside it with the same name as one in the enclosing class **shadows** the outer one for unqualified references. Unqualified `x` resolves to the nearest enclosing scope that declares `x` — the inner class first. To pierce the shadow you qualify: `Outer.this.x`. Captured *local* variables can't be shadowed-then-reached the same way, since you can't have two locals of the same name in scope. ## Lambdas: no `this` of their own A **lambda expression** is deliberately *not* a new scope for `this`. The Java Language Specification says a lambda's body sees `this`, `super`, and simple names exactly as the **enclosing context** does. So inside a lambda: ```java class Outer { int x = 10; Runnable make() { return () -> { System.out.println(this.x); // 10 -> `this` is the Outer instance System.out.println(x); // 10 -> same }; } } ``` There is **no** `Outer.this` distinction inside a lambda, because there is only one `this` — the enclosing one. This is sometimes called 'lexical `this`'. ## Why the difference matters in practice 1. **Refactoring hazard.** Turning an anonymous class into a lambda (or vice versa) changes the meaning of `this`. A listener written as `new Listener() { void on() { source.remove(this); } }` removes the *listener* object; the lambda form `e -> source.remove(this)` would try to remove the *enclosing* object — a bug. 2. **Self-reference.** Only an anonymous/local class can refer to *itself* via `this` (to deregister, store itself, etc.). A lambda cannot reference itself with `this`; you'd need a named field. 3. **Debugging / class files.** Each anonymous class compiles to `Outer$1.class`, `Outer$2.class`, … and shows up as such in stack traces; lambdas appear as synthetic methods (`lambda$make$0`). Named local classes give the most readable stack traces. ## Local classes follow the anonymous rules A named local class behaves like the anonymous case for `this`: `this` is the local-class instance, `Outer.this` reaches the enclosing instance, and names can shadow. The only difference is that the local class has a name (so it can be instantiated multiple times and have constructors).
- What can break when you convert an anonymous class to a lambda?Any use of `this` (or `super`, or shadowed simple names). In the anonymous class `this` is the inner instance; in the lambda it becomes the enclosing instance. Self-deregistration, `this`-based identity, and shadowed fields all change meaning.
- How do you reference the enclosing instance from inside an anonymous class?Use qualified this: `EnclosingClassName.this`. The non-static inner class holds a hidden reference to the enclosing instance, exposed through that syntax.
saying these in an interview costs you the question
- Saying `this` inside an anonymous class is the enclosing object
- Saying a lambda has its own `this`
- Assuming an anonymous-class-to-lambda refactor never changes semantics
- Believing you can reach the enclosing instance from a lambda with `Outer.this`