深入理解super关键字
super关键字总是指向当前对象的父类对象的引用
super关键字的作用
- 在子类的构造器中显示调用父类的构造器
- 在子类中访问父类中定义的、被隐藏的成员变量或父类中定义的、被重写的(Override)的成员方法
调用父类构造器
package com.ch05;
class Base{
public double size;
public String name;
public Base(double size, String name){
this.size = size;
this.name = name;
}
}
public class Sub extends Base{
public String color;
public Sub(double size, String name, String color){
super(size, name);
this.color = color;
}
public static void main(String[] args) {
Sub sub = new Sub(5.6, "测试对象", "黑色");
System.out.println(sub.size + "---" + sub.name + "---" + sub.color); // 5.6---测试对象---黑色
}
}
子类构造器调用父类构造器分如下几种情况:
- 子类构造器执行体的第一行使用super显式调用父类构造器,系统将根据super调用里传入的实参列表调用父类对应的构造器。
- 子类构造器执行体的第一行代码使用this显式调用本类中重载的构造器,系统将根据this调用里传入的实参列表调用本类中的另一个构造器。执行本类中另一个构造器时也会先调用父类构造器。
- 子类构造器执行体中既没有super调用,也没有this调用,系统将会在执行子类构造器之前,隐式调用父类无参数的构造器。
访问父类成员变量和方法
package com.ch05;
class BaseClass{
public int a = 5;
}
public class SubClass extends BaseClass {
public int a = 10;
public void accessSub(){
System.out.println(a);
}
public void accessBase(){
System.out.println(super.a);
}
public static void main(String[] args) {
SubClass subClass = new SubClass();
subClass.accessSub(); // 10
subClass.accessBase(); // 5
}
}
如果在某个方法中访问名为a的成员变量,但没有显式指定调用者,则系统查找a的顺序为:
- 查找该方法中是否有名为a的局部变量。
- 查找当前类中是否包含名为a的成员变量。
- 查找a的直接父类中是否包含名为a的成员变量,依次上溯a的所有父类,直到java.lang.Object类,如果最终不能找到名为a的成员变量,则系统出现编译错误。
如果被覆盖的是类变量,在子类的方法中则可以通过父类名作为调用者来访问被覆盖的类变量。
当程序创建一个子类对象时,系统不仅会为该类中定义的实例变量分配内存,也会为它从父类继承得到的所有实例变量分配内存,即使子类定义了与父类中同名的实例变量。也就是说,当系统创建一个Java对象时,如果该Java类有两个父类(一个直接父类A,一个间接父类B),假设A类中定义了2个实例变量,B类中定义了3个实例变量,当前类中定义了2个实例变量,那么这个Java对象将会保存2+3+2个实例变量。