library
beginnerVariable Scoping & Shadowing
Know how Java resolves variable names when local, instance, and class-level variables share the same name.
A variable is visible from its declaration to the end of its enclosing block. When two names collide, the innermost wins — that is shadowing.
Like nested Russian dolls: open the smallest one first (local scope). If the name isn't there, open the next bigger one (instance scope), then the next (class scope).
Key Concepts
1
class Counter {
int count = 10; // field2
void bump(int count) { // parameter shadows the field
count++; // the PARAMETER -- field unchanged
this.count++; // the field
}
}3
That is the bug. count++ looks like it updates the object and does not. The field needs this..
count++this.
4
The scopes, innermost outward.
block a for variable, a catch parameter
method parameters and locals
instance fields, reachable as this.x
class static fields, reachable as ClassName.x5
You cannot redeclare a local in an overlapping scope.
int x = 1;
{ int x = 2; } // will not compile6
Which differs from C, and from field shadowing, which is allowed.
7
A lambda cannot shadow an enclosing local either:
int x = 1;
run(y -> { int x = 2; }); // will not compile8
Lambdas share the enclosing scope rather than creating a nested one, unlike an anonymous class, which can
shadow.
9
Block scoping is tighter than people expect.
for (int i = 0; i < 10; i++) { }
print(i); // will not compile10
The same applies to try-with-resources variables and, since Java 14, to a pattern variable in a switch
case, which is scoped to its own branch.
11
A static field shadowed by an instance field needs ClassName.field to reach. It is legal and almost
always a mistake.
ClassName.field
12
The practical rule. Name things so shadowing never arises. this.name = name in a setter is the one
accepted exception, because the parameter name matching the field is clearer than inventing newName.
this.name = namenewName
13
What the interviewer is probing.1. "What is shadowing and where is it acceptable?" Probing: whether you treat it as a rule or
a judgement. Stalls: "It is always bad." Moves up: an inner name hiding an outer one; the
accepted case is a setter parameter matching the field, resolved with this.
14
2. "Can a lambda declare a variable with the same name as an enclosing local?" Probing: how
lambdas scope compared with anonymous classes. Stalls: "Yes, it is a new scope." Moves up: no —
a lambda shares the enclosing scope, so it does not compile, while an anonymous class can shadow.
15
3. "Why does a for-loop variable disappear after the loop?" Probing: block scoping. Stalls:
"It is cleaned up." Moves up: it is scoped to the loop's block, so referencing it afterwards does
not compile — the same applies to try-with-resources and switch pattern variables.
16
4. "Where do you have to qualify a name to reach what it shadows?" Probing: the qualifiers.
Stalls: "You cannot." Moves up: this.field for an instance field, ClassName.field for a static
one.