In Java, can an inner block declare a variable with the same name as one in an enclosing block?
answer
- Local-shadows-local: forbidden (compile error)
- Local-shadows-field: allowed, field via this.name
- Inner block can USE outer locals, not redeclare
- Sibling blocks may reuse names (no overlap)
- for-header var scoped to header + body
basics
~20 sNo. Unlike fields, a local variable in an inner block cannot reuse the name of a local variable from an enclosing block — the compiler reports an error. The inner block can still see the outer variable, but it cannot redeclare it.
solid answer
~40 sAn inner block can read and use a local variable declared in an enclosing block, because the inner block's scope is contained within the outer one. But Java forbids declaring a new local variable in an inner block with the same name as a local variable that is already in scope from an enclosing block — this is a compile error, not legal shadowing. This is a deliberate language rule to avoid confusing overlap of local names. Shadowing IS allowed in other directions: a local variable or parameter may shadow a field of the same name (the field is still reachable via this.name), and a parameter may shadow a field. So the key distinction is local-shadows-local (forbidden) versus local-shadows-field (allowed).
code
java · 13 linesclass C {
int count = 0;
void inc(int count) { // parameter shadows the field (allowed)
this.count += count; // field via this.count; param via count
System.out.println(count); // refers to the parameter
}
void siblings(boolean b) {
if (b) { int x = 1; System.out.println(x); }
else { int x = 2; System.out.println(x); } // OK: scopes don't overlap
}
}go deeper
Knows you cannot declare two variables with the same name in overlapping scopes and gets a compile error if you try.
Distinguishes local-shadows-local (forbidden) from local-shadows-field (allowed) and uses this.name to reach a shadowed field.
Explains the readability rationale, the for-header scoping subtlety, and that sibling non-overlapping blocks may reuse names.
Can cite the JLS scoping rules precisely, weighs shadowing against style guidelines (many teams ban shadowing fields), and reasons about how it affects refactoring safety and tooling lints.
## Setup: nested blocks Blocks can be **nested** — a block inside another block. Each `{ }` introduces its own scope, and an inner block sits inside the scope of every block that encloses it. ```java { // outer block int a = 1; { // inner block // a is visible here System.out.println(a); } } ``` The inner block can freely **read and modify** `a` because `a`'s scope (declaration to the outer closing brace) covers the inner block too. ## The forbidden case: redeclaring a local name What you **cannot** do is declare a *new local variable* in the inner block using a name that is already a local variable in an enclosing block: ```java { int a = 1; { int a = 2; // COMPILE ERROR: variable a is already defined } } ``` This is **not** legal shadowing. Java's language specification says a local variable's name may not be the same as another local variable (or parameter) whose scope includes the new declaration. The rationale is readability: having two different `a`s overlapping in nested local scopes is error-prone, so the language simply bans it. ## What 'shadowing' actually is **Shadowing** is when a name in an inner scope hides a *different kind* of declaration with the same name from an outer scope. In Java the allowed forms are: - A **local variable or parameter** shadows a **field** of the same name. - A nested type's member shadows an outer one (less common day-to-day). Local-shadows-field is legal and common: ```java class C { int count = 0; // field void inc(int count) { // parameter shadows the field this.count += count; // field via this.count; parameter via count } } ``` Inside `inc`, the bare name `count` refers to the **parameter** (the nearer declaration); the field is still reachable as `this.count`. That is the escape hatch shadowing provides. ## Sibling (non-nested) blocks: reuse is fine Two blocks that do **not** nest — for example, two separate `if` bodies, or two sequential bare blocks — may each declare a variable with the same name, because their scopes do not overlap: ```java if (cond) { int x = 1; ... } // x scoped to this block else { int x = 2; ... } // a different x, no conflict ``` ## The loop-variable subtlety A `for` statement's header introduces variables (e.g. `for (int i = ...)`) whose scope is the header **and** the loop body. So you cannot redeclare `i` inside that body, but two separate `for` loops in the same method may each use `i`. ## Summary rule - Inner block **uses** an outer local variable: allowed. - Inner block **redeclares** an outer local variable's name: forbidden (compile error). - Local variable/parameter **shadows a field**: allowed (field via `this.`). - Sibling, non-overlapping blocks reusing a name: allowed.
- How do you access a field that a parameter is shadowing?Qualify it with this — this.fieldName refers to the field, while the unqualified name refers to the nearer parameter/local.
- Why does Java forbid local-shadows-local but allow local-shadows-field?Overlapping local names in nested scopes are easy to misread, so the language bans them. A field has a stable, qualifiable home (this.x), so shadowing it is unambiguous and useful, e.g. in setters/constructors.
saying these in an interview costs you the question
- Saying inner blocks can shadow outer local variables like in C++/JavaScript
- Confusing local-shadows-field (allowed) with local-shadows-local (forbidden)
- Thinking the outer local is invisible inside the inner block
- Believing two separate if/else blocks cannot both declare 'x'