skip to content

What is variable shadowing in Java, and can you give a common example?

level: juniorimportance: must knowfreq 70%

answer

  1. Inner scope hides same-named outer variable
  2. Name resolves innermost-first
  3. Classic: parameter vs field
  4. this.field reaches the shadowed field
  5. this.name = name is the idiom

basics

~20 s

Shadowing happens when a variable in an inner scope has the same name as one in an outer scope, so the inner one hides the outer one. A classic case is a constructor parameter named the same as a field.

solid answer

~40 s

Variable shadowing occurs when a variable declared in a narrower (inner) scope has the same name as a variable in an enclosing (outer) scope. Inside the inner scope the bare name refers to the inner variable, so the outer one is temporarily hidden, or shadowed. The most common example is a constructor or setter whose parameter has the same name as a field: inside the method, the plain name refers to the parameter, not the field. To reach the shadowed field you qualify it with this, as in this.name = name. Shadowing is legal Java and often intentional, since it keeps parameter names meaningful, but accidental shadowing can cause bugs where you read or write the wrong variable.

code

java · 10 lines
java
class Person {
    private String name;
    Person(String name) {       // parameter shadows the field
        this.name = name;       // this.name = field, name = parameter
    }
    String describe() {
        String name = "local";  // local shadows the field here
        return name + " / " + this.name; // "local / <field value>"
    }
}

go deeper

for a junior

Can define shadowing, recognize the parameter-vs-field case, and fix it with this.field = field.

for a middle

Explains name resolution as innermost-first, distinguishes shadowing from overriding/hiding, and spots accidental shadowing in review.

for a senior

Discusses where shadowing is idiomatic vs risky, the local-vs-local error rule, and lints/conventions that catch accidental shadowing.

for a principal

Frames shadowing within language scope-resolution rules, weighs team naming conventions and static-analysis policy, and teaches the distinction from field hiding cleanly.

## Scope first In Java, every variable lives in a **scope** — the region of code where the name is visible. Scopes nest: a method body sits inside a class, a loop body sits inside a method, and so on. An **inner** (or narrower) scope is one nested inside an **enclosing** (outer) scope. ## What shadowing is **Variable shadowing** is when you declare a variable in an inner scope with the **same name** as a variable that already exists in an enclosing scope. Java resolves a bare (unqualified) name by searching from the innermost scope outward and stopping at the **first** match. So inside the inner scope, the name refers to the **inner** variable; the outer variable still exists but is **hidden** — you cannot reach it by its plain name. The outer variable is said to be *shadowed*. ## The canonical example: parameter shadows a field A **field** (also called an instance variable) is a variable declared directly in a class. A **parameter** is a variable declared in a method's signature. When both have the same name, inside that method the name means the **parameter**: ```java class Person { private String name; // field Person(String name) { // parameter shadows the field name = name; // BUG: assigns the parameter to itself; field untouched } } ``` The line `name = name` does nothing useful: both sides refer to the parameter. The field stays null. ## Disambiguating with `this` `this` is a reference to the current object. `this.name` always means the **field** `name` of the current object, regardless of any shadowing local variable or parameter. So the fix is: ```java Person(String name) { this.name = name; // left = field, right = parameter } ``` This idiom — parameter named like the field, `this.field = field` — is extremely common and considered idiomatic, not a smell. ## Where shadowing can appear - A **parameter** shadowing a field (most common). - A **local variable** shadowing a field. - A local variable or parameter shadowing an inherited field from a superclass. Note: Java does **not** let two locals in *overlapping* block scopes share a name (that is a compile error), so a local cannot shadow another local in the same nested-block chain — shadowing is between a local/parameter and a **field**, or across class scopes. ## Why it matters Intentional shadowing keeps parameter names readable. Accidental shadowing is a classic source of silent bugs: you think you are touching the field but you are touching the local. Knowing that bare names resolve innermost-first, and that `this.x` reaches the field, lets you read and fix such code with confidence.

  • Why does name = name in a constructor leave the field null?
    Both occurrences resolve to the parameter (innermost scope wins), so it assigns the parameter to itself; the field is never written and keeps its default null.
  • Is shadowing a parameter over a field bad practice?
    No. It is idiomatic when paired with this.field = field. It only becomes a problem when accidental and the field reference is forgotten.

Like a local nickname overriding a person's legal name in a small room: while you're in the room, the nickname wins; step out (use this) to use the legal name.

saying these in an interview costs you the question

  • Saying shadowing is a compile error (it is legal Java)
  • Confusing shadowing with overriding (overriding is for methods/polymorphism)
  • Thinking the outer variable is destroyed rather than just hidden
  • Believing two locals in overlapping scopes can shadow each other (that is an error)

context