变量遮蔽是指局部变量与成员变量同名时,局部变量在作用域内覆盖成员变量的可见性,导致直接访问变量名时实际访问的是局部变量;被遮蔽的成员变量仍存在,可通过this.变量名或类名.变量名显式访问。

当局部变量名与成员变量名相同时,局部变量会“遮蔽”(Shadowing)同名的成员变量,导致在该作用域内直接访问变量名时,实际访问的是局部变量而非成员变量。
什么是变量遮蔽
变量遮蔽是指在某个作用域中声明了一个与外部作用域(如类级别)同名的变量,从而使得外部变量在该作用域内不可直接访问。Java 中常见于方法内声明的局部变量与类的字段同名。
- 遮蔽只发生在**编译期可见性层面**,不影响成员变量本身的存在或值
- 被遮蔽的成员变量仍可通过 this.变量名 显式访问
- 静态变量被遮蔽时,可用 类名.变量名 访问
遮蔽的典型场景
最常见的是构造器或方法中用参数名或局部变量名与字段名一致:
public class Person {
private String name;
public Person(String name) {
name = name; // ❌ 错误:参数遮蔽了字段,赋值无效
}
}
此时右侧的 name 是参数(局部变量),左侧也是它自己,字段 this.name 没有被赋值。
- 正确写法是 this.name = name;
- IDE 通常会对这类遮蔽给出警告(如 “Assignment to itself”)
- 遮蔽也可能发生在嵌套作用域,比如 for 循环中声明同名变量
如何避免或应对遮蔽
遮蔽本身不是语法错误,但容易引发逻辑错误和可读性问题。推荐做法包括:
- 命名规范:成员变量加前缀(如 mName、name_)或使用 this. 显式标识
- 启用编译器/IDE 警告:如 javac 的 -Xlint:shadow 可检测潜在遮蔽
- 必要时主动使用 this.field 或 ClassName.staticField 消除歧义
- 避免在 lambda 或匿名类内部声明与外层同名变量,防止意外遮蔽
遮蔽 vs 隐藏(Hiding) vs 重写(Overriding)
注意区分三个概念:
- 遮蔽(Shadowing):变量层面,局部变量盖住字段或参数
- 隐藏(Hiding):静态成员被子类同名静态成员覆盖(不涉及多态)
- 重写(Overriding):实例方法被子类同签名方法替换(支持运行时多态)
遮蔽是静态绑定,完全由代码书写位置决定;后两者分别作用于静态上下文和动态方法调用。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











