skip to content

In Java, can an inner block declare a variable with the same name as one in an enclosing block?

level: middleimportance: must knowfreq 60%

answer

  1. Local-shadows-local: forbidden (compile error)
  2. Local-shadows-field: allowed, field via this.name
  3. Inner block can USE outer locals, not redeclare
  4. Sibling blocks may reuse names (no overlap)
  5. for-header var scoped to header + body

basics

~20 s

No. 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 s

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

for a junior

Knows you cannot declare two variables with the same name in overlapping scopes and gets a compile error if you try.

for a middle

Distinguishes local-shadows-local (forbidden) from local-shadows-field (allowed) and uses this.name to reach a shadowed field.

for a senior

Explains the readability rationale, the for-header scoping subtlety, and that sibling non-overlapping blocks may reuse names.

for a principal

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'

context