首先创建两个类Person和Student,Student继承自Person,里面随便定义一些属性和方法
package com.wen4;
public class Person {
int age;
public void eat(){
System.out.println("eat");
}
}
package com.wen4;
public class Student extends Person{
double score;
public void study(){
System.out.println("learn");
}
public void practice(){
System.out.println(age);
eat();
}
}
因为Student继承自Person,所以Student里面practice方法里面的age指的是父类Person中的age,eat方法指的是父类Person中的方法,但是我们如何显示的表达出来,可以在前面加上"super."
public void practice(){
System.out.println(super.age);
super.eat();
}
所以由案例可以总结
- super指的是:父类的
- super可以修饰属,方法
在子类方法中,可以通过super.属性 super.方法的方式,显示调用父类提供的属性方法,通常情况下可不写
但是在特殊情况下super.不能省略
package com.wen4;
public class Student extends Person{
int age = 20;
double score;
public void study(){
System.out.println("learn");
}
public void eat(){
System.out.println("student类中的eat方法");
}
public void practice(){
System.out.println(super.age);
super.eat();
}
}
此时子类Student中也有age属性和eat方法的重写,如果不加super关键字,那么程序会遵循就近原则,优先使用子类Student中的age属性和eat方法,此时相当于省略this关键字,如下:
public void practice(){
System.out.println(this.age);
this.eat();
}
所以由此案例可以总结:
- 当子类中属性与父类中属性重名时,如果要想要使用父类中的属性,不能省略super.
- 子类中存在方法重写,使用父类中的方法就不能省略super.
依旧举例说明
package com.wen5;
public class Person {
int age;
String name;
public Person(){
}
}
package com.wen5;
public class Student extends Person {
double score;
public Student(){
}
}
package com.wen5;
public class Test {
public static void main(String[] args) {
Student xiaoWen = new Student();
}
}
这里创建一个xiaoWen对象,首先程序执行到这一步,先进行类的加载(这个不懂可以跳过,不影响),然后进入到Student类的构造器中,然后进入Person类的构造器中,所以实际上,当创建一个对象时,程序会一层一层向上调用构造器进行类的初始化操作,就如例子:Studnet ==> Person ⇒ Object.
程序中就相当于省略了super(); 一般情况下省略不写
package com.wen5;
public class Student extends Person {
double score;
public Student(){
super();
}
}
下面我们使用super()调用父类构造器进行属性初始化,更深入理解super的妙用
package com.wen5;
public class Person {
int age;
String name;
public Person(){
}
public Person(int age, String name){
this.age = age;
this.name = name;
}
}
package com.wen5;
public class Student extends Person {
double score;
public Student(int age, String name, double score){
super(age, name); // 调用父类的构造器
this.score = score;
}
}
在构造器中,super调用父类构造器和this调用子类构造器只能存在一个,二者不能共存.
表层原因:
super修饰构造器只能放在第一行,this修饰构造器也要放在第一行
深层原因:
假如可以存在(错误案例,便于理解,实际不能运行)
package com.wen5;
public class Student extends Person {
double score;
public Student(double score){
super();//程序默认分配了,不写,这里显示的写出来,方便理解
this.score = score;
}
public Student(int age, String name, double score){
super(age, name);
this(score);
}
}
super(age, name)对父类Person进行了一次初始化,当执行到this(score),再一次执行super(),相当于再一次初始化Person,冲突了也就是所谓的不合理,所以在构造器中,表示调用构造器时候,this和super不能同时存在
注意:
总结:一般情况下,所有的构造器第一行默认情况下都有super(),但是一旦显示的使用了super()调用了父类构造器或者使用this()调用了子类构造器,那么这个 super()就不会给你默认分配了
super关键字:引用父类的,找父类的xx
用法:
(1)super.属性
当子类声明了和父类同名的成员变量时,那么如果要表示某个成员变量是父类的,那么可以加“super.”
(2)super.方法
当子类重写了父类的方法,又需要在子类中调用父类被重写的方法,可以使用"super."
(3)super()或super(实参列表)
super():表示调用父类的无参构造
super(实参列表):表示调用父类的有参构造
注意:
(1)如果要写super()或super(实参列表),必须写在子类构造器的首行
(2)如果子类的构造器中没有写:super()或super(实参列表),那么默认会有 super()
(3)如果父类没有无参构造,那么在子类的构造器的首行“必须”写super(实参列表)
(4)构造器中super调用父类构造器和this调用子类构造器不能共存



