变量作用域遮蔽是编译期静态绑定行为,非运行时错误;只对非private父类字段有效,需通过不同引用类型访问验证,借助ide或编译器警告快速定位,修复应删除重复字段或改用新名及封装getter/setter。

变量作用域遮蔽不是运行时错误,而是编译期就确定的静态绑定行为。排查重点不在“程序崩没崩”,而在“谁在看、从哪看”——即访问变量时的引用类型,决定了实际读写的是哪个字段。
确认是否真发生了字段遮蔽
遮蔽只对非private的父类字段有效(如public、protected、包级私有)。检查子类中是否显式声明了同名、同类型的实例变量:
- 父类有 protected String name;,子类也写 protected String name; → 遮蔽成立
- 父类是 private int id;,子类再声明 int id; → 不算遮蔽(子类本就不能直接访问 private 字段)
- 子类只重写了 getName() 方法,没声明新字段 → 是正常继承,不是遮蔽
验证访问路径与实际读取值
同一对象,用不同引用类型访问同名字段,会得到不同结果。这是最直观的验证方式:
- Parent p = new Child(); System.out.println(p.state); → 输出父类字段的值
- Child c = new Child(); System.out.println(c.state); → 输出子类字段的值
- 在子类方法里加日志:System.out.println("super.state=" + super.state + ", this.state=" + this.state); → 可同时看到两个独立值
借助工具快速定位
别靠肉眼扫代码,用工具第一时间暴露问题:
- IDE 悬停变量名,提示 “shadows field from superclass” 就是明确信号
- 启用编译器警告:javac -Xlint:shadow,编译时直接报出遮蔽位置
- IntelliJ 或 Eclipse 中开启 “Field hides a superclass field” 检查项
- 静态分析工具如 SonarQube、PMD 也能识别该模式并标记为高危
修复策略与安全写法
保留同名字段风险高,应主动消除歧义:
- 子类删掉重复字段声明,统一通过 super.state 操作父类状态
- 若需扩展状态,改用新字段名(如 childState),并加注释说明职责
- 把状态封装进 protected 的 getter/setter 中,子类重写逻辑而非覆盖字段
- 构造器或 setter 中,参数一律用 this.field = field; 明确赋值目标,避免参数遮蔽字段











