文章目录
- 1. 功能
- 2. 代码中理解
- 3. super调用父类构造器
- 3.1. 结论一证明
- 3.2. 结论二证明
- 4. this和super的区别
1. 功能
- 在 Java 类中使用 super 来调用父类中的指定操作:
(1)super 可用于访问父类中定义的属性
(2)super 可用于调用父类中定义的成员方法
(3)super 可用于在子类构造方法中调用父类的构造器
注意:
(1)尤其当子父类出现同名成员时,可以用super
进行区分
(2)super 的追溯不仅限于直接父类,在多层继承中,使用super,子类可以调用子类之上所有的父类
(3)super 和 this 的用法相像, this 代表本类对象的引用, super 代表父类的内存空间的标识
2. 代码中理解
层级关系:Kk(子类)–>Kids(父类)–>ManKind(父类的父类)
代码:
ManKind类
package day07;
public class ManKind {
int sex;
int salary;
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public void manOrWoman() {
if(this.sex == 1) {
System.out.println("man");
}else if(this.sex == 0) {
System.out.println("Woman");
}
}
public void employeed() {
if(this.salary == 0) {
System.out.println("no job");
}else {
System.out.println("job");
}
}
}
Kids类
package day07;
public class Kids extends ManKind {
int yearsOld;
public int getYearsOld() {
return yearsOld;
}
public void setYearsOld(int yearsOld) {
this.yearsOld = yearsOld;
}
public void printAge() {
System.out.println(this.yearsOld);
}
public static void main(String[] args) {
Kids someKid = new Kids();
someKid.setSex(0);
someKid.setSalary(100);
someKid.manOrWoman();
someKid.employeed();
}
}
Kk类
package day07;
public class Kk extends Kids {
public void test() {
//追溯 ManKind类中的salary变量
super.salary = 1;//可以使用super向上追溯父类的父类;如果有多个层级的父类的话,可以一直向上追溯
//追溯 Kids类中的yearsOld变量
super.yearsOld = 1;//可以使用super直接追溯使用父类的成员变量
//追溯 Kids类中的employeed方法
super.employeed();//可以使用super直接追溯使用父类的成员方法
//追溯 ManKind类中manOrWoman方法
super.manOrWoman();//可以使用super直接追溯使用父类的父类的成员方法;如果有多个层级的父类的话,可以一直向上追溯
}
}
练习:
- 修改上述例题中定义的 类Kids中 employed() 方法,在该方法中调用父类 ManKind 的 employed() 方法,然后再输出“ but Kids should study and no job.”
package day07;
public class Kids extends ManKind {
int yearsOld;
@Override
public void employeed() {
// TODO Auto-generated method stub
super.employeed();//调用父类的employeed
System.out.println("but Kids should study and no job.");
}
public static void main(String[] args) {
Kids someKid = new Kids();
someKid.employeed();//调用子类的employeed
}
}
输出结果:
3. super调用父类构造器
三条结论:
(1)子类中所有的构造器默认都会访问父类中空参数的构造器。
(2)当父类中没有空参数的构造器时,子类的构造器必须通过 this(参数列表)
或者 super(参数列表)
语句指定调用本类或者父类中相应的构造器,且必须放在构造器的第一行。
(3)如果子类构造器中既未显式调用父类或本类的构造器,且父类中又没有无参的构造器,则编译出错。
3.1. 结论一证明
举例:(1)子类中所有的构造器默认都会访问父类中的无参构造器。
在父类ManKind中创建一个 空参数构造器
package day07;
public class ManKind {
//创建空参数构造器
public ManKind() {
System.out.println("ManKind");
}
int sex;
int salary;
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public void manOrWoman() {
if(this.sex == 1) {
System.out.println("man");
}else if(this.sex == 0) {
System.out.println("Woman");
}
}
public void employeed() {
if(this.salary == 0) {
System.out.println("no job");
}else {
System.out.println("job");
}
}
}
子类Kids:
package day07;
public class Kids extends ManKind {
int yearsOld;
public static void main(String[] args) {
Kids someKid = new Kids();//new Kids()是在调用Kids类的默认无参构造方法,这个过程就会使用到父类的无参构造
}
}
运行结果:
当然,也可以在子类中显示地调用父类的构造器
package day07;
public class Kids extends ManKind {
//显示地调用父类的构造器
public Kids() {
super();
}
int yearsOld;
public static void main(String[] args) {
Kids someKid = new Kids();
}
}
3.2. 结论二证明
举例:(2)当父类中没有空参数的构造器时,子类的构造器必须通过 this(参数列表)
或者 super(参数列表)
语句指定调用本类或者父类中相应的构造器,且必须放在构造器的第一行。
父类:显示创建有参构造器
package day07;
public class ManKind {
// public ManKind() {
// System.out.println("ManKind");
// }
//当存在显示的构造方法时,类就没有默认的无参构造了,而是要使用显示的构造
public ManKind(int sex, int salary) {
this.sex = sex;
this.salary = salary;
}
int sex;
int salary;
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public void manOrWoman() {
if(this.sex == 1) {
System.out.println("man");
}else if(this.sex == 0) {
System.out.println("Woman");
}
}
public void employeed() {
if(this.salary == 0) {
System.out.println("no job");
}else {
System.out.println("job");
}
}
}
此时,如果把上一个例子中Kids中的构造器注释掉的话,程序会报错:提示添加一个‘Kids(int,int)’构造器。如下图所示:
给Kids中添加有参构造器:
package day07;
public class Kids extends ManKind {
public Kids(int sex, int salary) {
//在父类只有有参构造可以使用的时候,子类必须显示的创建一个构造来调用父类的有参构造,
//并且调用父类构造方法要写在第一行
super(sex, salary);
// TODO Auto-generated constructor stub
}
int yearsOld;
public static void main(String[] args) {
Kids someKid = new Kids();
}
}
4. this和super的区别
序号 | 区别 | this | super |
---|---|---|---|
① | 访问属性 | 访问本类中的属性, 如果本类没有此属性则从父类中继续查找 | 访问父类中的属性 |
② | 调用方法 | 访问本类中的方法 | 直接访问父级中的方法 |
③ | 调用构造器 | 调用本类构造器,必须放在构造器首行 | 调用父类构造器,必须放在子类构造器的首行 |
④ | 特殊 | 表示当前对象 | 无此概念 |
注意:
根据③:在子类中,通过this或者是super调用构造器,只能使用一个,因为都要占据第一行