我们知道类的组成是成员变量,构造方法,成员方法
1. this代表本类对应的引用。输出本类成员范围的num
2. super代表父类存储空间的标识(可以理解为父类引用,可以操作父类的成员)。 输出父类成员范围的num
用法:
A:调用成员变量
this.成员变量 调用本类的成员变量
super.成员变量 调用父类的成员变量
B:调用构造方法
this(...) 调用本类的构造方法
super(...) 调用父类的构造方法
C:调用成员方法
this.成员方法 调用本类的成员方法
super.成员方法 调用父类的成员方法
在子类方法中访问一个变量的查找顺序: //通过子类对象调用变量就没有第一步了(在子类方法找).
1.子类中的成员变量和父类中的成员变量名称不一样时。 【分别调用】
2.子类中的成员变量和父类中的成员变量名称一样时。 【默认就近原则】
//在[子类方法]的局部范围找,
//在[子类]的成员范围找,
//在[父类]的成员范围找,如果还找不到,就报错。
使用super关键字可以打破就近原则,直接指定想访问的父类成员变量。--->一般通常是在子类方法中发生。
子类方法中调用变量:
1. int num1 = super.num; //将父类的num变量赋值给子类的num1变量;子类对象调用s.num1
2.
public void show(){
Syste,.out.println(super.num); //将父类中的成员变量在子类的成员方法中输出;子类对象调用s.show()
}
子类对象调用变量:
- 代码详解
//默认使用就近原则
class Father {
public int num = 10;
public void method() {
int num = 100;
}
}
class Son extends Father {
public int num2 = 20;
public int num = 100;
public void show() {
int num = 1000;
int num3 = super.num; //将父类的成员变量赋值给子类
System.out.println(num); //1000,使用就近原则。
System.out.println(num2); //20
System.out.println(this.num); //100,调用本类的成员变量
System.out.println(super.num); //10,调用父类的成员变脸
}
}
//通过子类对象调用方法
1. 子类中的方法和父类中的方法声明不一样。 【各调各的】
2. 子类中的方法和父类中的方法声明一样。 【默认就近原则】
// 先找子类中,再看父类中,如果没有就报错。
也可以使用super关键字打破就近原则,直接指定想访问的成员方法。---->也叫做方法重写。
public father_method(){
super.show() //调用父类的show方法。 子类对象通过s.father_method()调用父类方法。
}
方法重写:子类中出现了和父类中方法声明一模一样的方法。 【方法名一样,参数列表一样。】
方法重载:本类中出现的方法名一样,参数列表不同的方法。与返回值无关。【方法名一样,参数列表不同。】
//子类对象调用方法的时候,先找子类本身,再找父类。
方法重写的应用:
当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容。
- 方法重写的注意事项:
子类重写父类方法的时候,最好声明一模一样。
1.父类的私有方法(private)子类无法继承,所以父类中私有方法不能被重写。
2.子类重写父类方法时,访问权限(public)不能更低,建议保持一致。
3.父类的静态方法(static),子类也必须通过静态方法进行重写。
//其实这个在多态中算不上方法重写,但是现象确实如此。
代码详解:
class Father {
public void show() {
System.out.println("show Father");
}
public static void method() {
}
}
class Son extends Father {
public void show() { //重写父类show方法
System.out.println("show Son");
}
public static void method() {
//父类的静态方法,子类也必须通过静态方法进行重写。
}
}
class ExtendsDemo10 {
public static void main(String[] args) {
Son s = new Son();
s.show();
}
}
1. 子类中的所有构造方法默认都会访问父类中无参数的构造方法。
但如果父类没有无参构造方法,那么子类的构造方法会出现报错。
//因为子类会继承父类中的数据,可能还会使用父类的数据,所以子类初始化之前,一定要先完成父类数据的初始化。
所以可能有一下几种情况:
1.父类中必须要有一个无参构造方法
2.通过使用super关键字去调用父类的带参构造方法
3.子类通过this去调用本类的其他构造方法
//子类中一定要有一个去访问了父类的构造方法,否则父类数据就没有初始化。
注意:
子类每一个构造方法的第一条语句默认都是:super();
this(...)或者super(...)必须出现在第一条语句上。
//如果不是放在第一条语句上,就可能对父类的数据进行了多次初始化,所以必须放在第一条语句上。
- 不管子类使用哪种构造方法(有参或无参)进行类的初始化,首先都是会默认调用父类的无参构造方法进行父类初始化。
默认是调用父类的无参构造方法进行初始化的,但是现在父类没有无参构造方法,所以要指定调用父类的有参构造方法。
如果不指定会出现找不到父类无参构造方法而报错。