Java学习笔记之深入理解关键字super

为什么需要super

考虑这样一个情景,当一个类继承自另一个类,并重写了父类的一个方法,并且想在这个方法中调用父类的这个方法,该如何做呢?当然,我们不能直接调用该方法,因为它会产生递归。这时,我们就需要通过super.方法名来访问父类的该方法。
当然,super的存在不仅仅如此。我们知道,当创建一个导出类(即通过继承而来)的对象时,该对象会包含一个基类的子对象。这就需要我们正确的对基类子对象进行初始化。如何正确的基类子对象进行初始化呢?这时,super就派上用场了。当基类构造器不带有参数,Java会自动在导出类的构造器中插入对基类构造器的调用(即隐式的使用了super()),而不需手动编写。但如果基类构造器是带有参数的,那就必须得手动编写,显式的插入带有相应参数的super(参数列表)方法,而且,值得注意的是,必须将该方法放在导出类构造器的第一行。
super还有另外一个用处,就是可以通过它来访问基类中被隐藏的成员变量(即被子类覆盖的成员变量,非private成员变量),引用格式:super.成员变量名

如何使用super

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package com.gongchuangsu.reusing;

class Animal{
public String s1 = "str_1 in Animal";
public String s2 = "str_2 in Animal";

public Animal(int i) {
System.out.println("Animal");
}

public void f(){
System.out.println("Animal say...");
}
}

class Dog extends Animal{
public String s1 = "str_1 in Dog";
public String s2 = "str_2 in Dog";

public Dog(int i) {
super(i);
System.out.println("Dog");
}

public void f(){
System.out.println("Dog say...");
}
}

public class Teddy extends Dog{
public String s1 = "str_1 in Teddy";

public Teddy(int i) {
super(i); // 调用父类带参构造函数完成父类初始化,其必须放在第一行
System.out.println("Teddy");
}

public void f(){
System.out.println(s1); // 访问所在类的成员变量
System.out.println(s2); // 访问父类的成员变量
System.out.println(super.s1); // 访问父类被隐藏的成员变量,即被子类覆盖的成员变量
System.out.println("Teddy say...");
}

public static void main(String[] args){
Teddy teddy = new Teddy(0);
teddy.f();
}
}
/*output
Animal
Dog
Teddy
str_1 in Teddy
str_2 in Dog
str_1 in Dog
Teddy say...
*/

参考资料

  1. Java编程思想