5.6.3 super限定

5.6.3 super限定

如果需要在子类方法中调用父类被覆盖的实例方法,则**可使用super限定来调用父类被覆盖的实例方法**。

superJava提供的一个关键字,super用于限定该对象调用它从父类继承得到实例变量实例方法

super不能出现在staitc修饰的方法中

正如this不能出现在static修饰的方法中一样, super也不能出现在static修饰的方法中。

如果在构造器中使用super,则super用于限定该构造器初始化的是该对象从父类继承得到的实例变量,而不是该类自己定义的实例变量。

子类同名实例变量会覆盖父类变量

如果子类定义了和父类同名的实例变量,则会发生子类实例变量隐藏父类实例变量的情形。
在正常情况下,子类里定义的方法直接访问该实例变量默认会访问到子类中定义的实例变量,无法访问到父类中被隐藏的实例变量
在子类定义的实例方法中可以通过super来访问父类中被隐藏的实例变量。

如果子类里没有包含和父类同名的成员变量,那么在子类实例方法中访问该成员变量时,则无须显式使用super父类名作为调用者。

系统查找变量的顺序

如果在某个方法中访问名为a的变量,但没有显式指定调用者,则系统查找a的顺序为:

  1. 查找该方法中是否有名为a的局部变量。
  2. 查找当前类中是否包含名为a的成员变量。
  3. 查找a的直接父类中是否包含名为a的成员变量,
  4. 如果没有依次上溯a的所有父类,直到java.lang.Object类,如果最终不能找到名为a的成员变量,则系统出现编译错误。

被覆盖的是类变量的情况

如果被覆盖的是类变量,在子类的方法中则可以通过父类名作为调用者来访问被覆盖的类变量

系统依旧为被覆盖的变量分配内存空间

如果在子类里定义了与父类中已有变量同名的变量,那么子类中定义的变量会隐藏父类中定义的变量。注意不是完全覆盖,因此系统在创建子类对象时,依然会为父类中定义的、被隐藏的变量分配内存空间

引用变量类型决定调用的是哪个实例变量

如果子类和父类存在同名的实例变量,

  • 当通过子类引用变量访问这个实例变量时,访问的是子类的实例变量,
  • 当在该子类引用变量强制向上转型为父类引用变量时,访问的是被覆盖的父类的成员变量。

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Parent {
// 父类实例变量
public String tag = "父类 实例变量 的值";
}

class Derived extends Parent {
// 子类实例变量,会覆盖父类
public String tag = "子类 实例变量 的值";
}

public class HideTest {
public static void main(String[] args) {
Derived d = new Derived();
// d现在是子类类型的引用变量,访问的是 子类中 新定义的 实例变量
System.out.println(d.tag);
// 向上转型后d变成父类类型的引用变量,访问的是 子类中 被隐藏的 父类实例变量
System.out.println(((Parent) d).tag);
}
}

运行效果:

1
2
子类 实例变量 的值
父类 实例变量 的值