super关键和this作用类似,是被屏蔽的成员变量或者成员方法或变为可见,或者说用来引用被屏蔽的成员变量和成员成员方法。
不过super是用在子类中,目的是访问直接父类中被屏蔽的成员,注意是直接父类(就是类之上最近的超类)。下面是一个综合运用super的例子,有两个类:一个Father类,一个Father类的子类Son,通过这两个类完全演示了super的用法,一下是代码:
public String v="Father";
public String x="输出了Father类的public成员变量x!!!";
public Father() {
System.out.println("Father构造方法被调用!");
}
public Father(String v){
this.v="Father类的带参数构造方法!运行了.";
}
public void outinfo(){
System.out.println("Father的outinfo方法被调用");
}
// TODO 自动生成方法存根
}
}
public Son() {
super(); //调用超类的构造方法,只能放到第一行.
System.out.println("Son无参数构造方法被调用!");
//super(); //错误的,必须放到构造方法体的最前面.
}
public Son(String str){
super(str);
System.out.println("Son带参数构造方法被调用!");
}
//覆盖了超类成员方法outinfo()
public void outinfo(){
System.out.println("Son的outinfo()方法被调用");
}
public void test(){
String v="哈哈哈哈!"; //局部变量v覆盖了成员变量v和超类变量v
System.out.println("------1-----");
System.out.println(v); //输出局部变量v
System.out.println(this.v); //输出(子类)成员变量v
System.out.println(super.v); //输出超类成员变量v
System.out.println("------2-----");
System.out.println(x); //输出超类成员变量v,子类继承而来
System.out.println(super.x); //输出超类成员变量v
System.out.println("------3-----");
outinfo(); //调用子类的outinfo()方法
this.outinfo(); //调用子类的outinfo()方法
super.outinfo(); //调用父类的outinfo()方法
}
public static void main(String[] args) {
new Son().test();
}
}
Son无参数构造方法被调用!
------1-----
哈哈哈哈!
Son
Father
------2-----
输出了Father类的public成员变量x!!!
输出了Father类的public成员变量x!!!
------3-----
Son的outinfo()方法被调用
Son的outinfo()方法被调用
Father的outinfo方法被调用
第一、在子类构造方法中要调用父类的构造方法,用“super(参数列表)”的方式调用,参数不是必须的。同时还要注意的一点是:“super(参数列表)”这条语句只能用在子类构造方法体中的第一行。
第二、当子类方法中的局部变量或者子类的成员变量与父类成员变量同名时,也就是子类局部变量覆盖父类成员变量时,用“super.成员变量名”来引用父类成员变量。当然,如果父类的成员变量没有被覆盖,也可以用“super.成员变量名”来引用父类成员变量,不过这是不必要的。
第三、当子类的成员方法覆盖了父类的成员方法时,也就是子类和父类有完全相同的方法定义(但方法体可以不同),此时,用“super.方法名(参数列表)”的方式访问父类的方法。
构造方法中的super关键字
在Java子类的构造方法中可以通过super关键字来调用父类的构造方法。其用法为:
1) super(); 访问父类中的无参构造函数
2) super (paras…); 访问父类中的成员函数yyy
super()来调用父类无参的构造方法,但即使不使用super(),默认也会调用父类无参的构造方法。父类无参的构造方法可以是自定义的无参构造方法,也可以是编译器自动生成的默认构造方法。但如果父类中定义了有参的构造方法,但没有定义无参的构造方法,这时编译器不会生成默认构造函数,也就不能通过super()来调用构造方法。此外,如果父类中定义了private的无参构造方法,也不同通过super()来调用。
super(paras…);用来调用父类中某个有参的构造方法。
super调用父类的构造方法,必须放在子类构造方法的第一行中执行。如果调用的有参的父类构造方法,在super的参数中不能用子类中的非static成员变量(可以使用static成员变量,因为static成员变量在构造方法执行前就已经初始化),也不能使用this或super的相关调用。例如super(super.getClass().getName());
在构造方法中也可以使用super关键字来访问父类中的成员变量和成员函数。其用法和非构造方法中的super关键字用法相同。
非构造方法中的super关键字
在Java子类中可以通过通过super关键字来调用父类中的成员变量和方法。其用法是。
1) super.xxx; 访问父类中的成员变量xxx
2) super.yyy(paras…); 访问父类中的成员函数yyy
super关键字访问父类的成员变量和成员函数时不能越过访问权限的控制,不能访问父类中private的成员变量和方法。例如:
class a {
private int mNum = 0;
}
class b extends a {
public void setNum(int i) {
super.mNum = i; //错误,不能访问父类的private成员
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
在有多层的继承关系时,super调用只能自身父类的成员变量和方法,不能越过父类直接调用父类的父类中的成员变量或方法。当然如果父类的父类中的成员变量或方法被父类继承,那么是可以通过super来调用该成员变量和方法的,但这时实际调用的是父类中的成员变量和方法。例如:
class a {
protected int mNum = 0;
public void setNum(int i) {
mNum = i;
}
}
class b extends a {
public void setNum(int i) {
mNum = i * i;
}
}
class c extends b {
public void setNum(int i) {
super.setNum(i); //调用的是b中的setNum()方法
super.super.setNum(i); //错误,不支持的用法
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
class a {
protected int mNum = 0;
public void setNum(int i) {
mNum = i;
}
}
class b extends a {
}
class c extends b {
public void setNum(int i) {
super.setNum(i); //正确,虽然b中没有实现setNum(),但b中继承了a的setNum()函数,
//c中调用super.setNum()调用的是b的setNum()函数,可以执行。
}
}