在Java的继承体系中,变量遮蔽指的是子类中声明了与父类同名的成员变量,从而隐藏了父类的变量。与此同时,方法中的局部变量也可能与成员变量同名,造成更细粒度的遮蔽。要准确访问不同作用域的变量,就需要结合this和super关键字。

什么是变量遮蔽
变量遮蔽分为两种常见情况:子类成员变量遮蔽父类成员变量,以及局部变量遮蔽成员变量。下面的例子展示了这两种情形:
class Parent {
String name = "父类名称";
}
class Child extends Parent {
String name = "子类名称";
void show() {
String name = "局部名称";
System.out.println(name); // 局部变量:局部名称
System.out.println(this.name); // 子类成员变量:子类名称
System.out.println(super.name); // 父类成员变量:父类名称
}
}
this关键字的作用
this代表当前对象实例的引用。当局部变量与成员变量同名时,使用this明确指向当前类的成员变量,避免被局部变量遮蔽。
在构造方法中区分参数与字段
class User {
private String name;
public User(String name) {
this.name = name; // 左侧this.name是成员,右侧name是参数
}
}
super关键字的作用
super用于访问父类的成员。当子类遮蔽了父类的变量时,通过super可以读取或修改父类被遮蔽的字段。
子类访问父类被遮蔽变量
class Base {
int value = 10;
}
class Derived extends Base {
int value = 20;
void printValues() {
System.out.println(value); // 20,子类变量
System.out.println(super.value); // 10,父类变量
}
}
this与super结合使用的注意点
- this和super都不能用在静态方法中,因为它们依赖对象实例。
- super不是指向父类对象,而是当前对象中父类部分成员的引用。
- 如果父类变量是private,则子类无法通过super直接访问,需借助父类提供的protected或public方法。
综合示例
下面代码演示了在子类构造方法中同时使用this和super初始化不同作用域的变量:
class Animal {
String type = "动物";
}
class Dog extends Animal {
String type = "狗";
String color;
Dog(String color) {
super(); // 调用父类构造
this.color = color; // 初始化子类自身字段
System.out.println(super.type); // 动物
System.out.println(this.type); // 狗
}
}
掌握变量遮蔽场景下this和super的使用方式,可以让你在多层继承中清晰地控制变量访问,减少隐藏bug。