super
调用父类属性
//首先写一个父类
public class Person {
protected String name = "1";
}
//然后写一个子类
public class Student extends Person{
private String name = "2";
public void test(String name){
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
}
//最后在Application类中写主程序方法
import OOP.demo.Student;
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.test("3");
}
}
====运行结果====
3 //这时主程序方法传参给子类的“name”
2 //这是子类中自己的“this.name”
1 //这是子类中调用父类的“super.name”
- 除了调用属性外,还能调用方法:
//在父类里写一个print方法
public class Person {
public void print() {
System.out.println("Person");
}
}
//在子类里也写一个print方法,输出不一样。再写一个test方法供Application类调用
public class Student extends Person{
public void print() {
System.out.println("Student");
}
public void test(){
print();
this.print();
super.print();
}
}
//在Application类中调用test方法
import OOP.demo2.Student;
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.test();
}
}
====运行结果====
Student
Student //“print()”和“this.print()”都是子类自己的方法,加上this更便于区分
Person //“super.print()”则是调用的父类方法
-
当父类中的属性、方法权限为
private
时,super
无法调用。 -
再从下面的例子看看
super
的特性
//父类中写一个无参构造
public class Person {
public Person() {
System.out.println("Person无参执行了");
}
}
//子类中写一个无参构造
public class Student extends Person{
public Student() {
System.out.println("Student无参执行了");
}
}
//Application类
import OOP.demo3.Student;
public class Application {
public static void main(String[] args) {
Student student = new Student();
}
}
====运行结果====
Person无参执行了
Student无参执行了
- 你会发现
new
一个子类中的方法时,却先执行了父类的无参构造。这是因为在子类的构造器中有一行隐藏的默认的代码super();
,在调用父类的无参构造。 - 而且,如果你显式定义了
super();
,然后试图在这行代码之上写子类的方法,会直接报错。也就是说,这行super();
必须在子类构造器的第一行。
public class Student extends Person{
public Student() {
super(); //可以显式地写出来,对运行无影响,别写到构造器外面去了
System.out.println("Student无参执行了");
}
}
- 下面的内容秦疆老师讲得很快,且不甚清晰,总之我尽力理清楚。
- 如果我们在子类中显式定义
super();
,再加一个有参构造,用this();
调用自身的有参构造,父类保持无参:
//父类==============================
public class Person {
public Person() {
}
}
//子类==============================
public class Student extends Person{
public Student() {
super();
this("name"); //报错
}
public Student(String name) { //一个有参构造
}
}
-
这时代码会报错:
this();
调用必须是构造函数主体中的第一条语句。 -
如果
this();
和super();
调换顺序,则会报错:super();
调用必须是构造函数主体中的第一条语句。 -
如果将父类中的无参构造改为有参构造,子类的无参构造中显式定义
super();
//父类==============================
public class Person {
public Person(String name) { //父类改成有参
}
}
//子类==============================
public class Student extends Person{
public Student() {
super(); //报错
}
}
- 按照之前所学,定义了有参构造,那么无参构造要么重新显式定义一个,要么就直接没了。这时,显式调用父类无参构造的
super();
会报错,因为父类的无参构造已经没有了。 - 若删除
super();
语句,子类的无参构造也会报错:父类中没有可用的默认构造参数。(这里的默认构造参数就是无参构造)。
//父类==============================
public class Person {
public Person(String name) {
}
}
//子类==============================
public class Student extends Person{
public Student() { //报错
}
}
- 若加上显式定义语句
super("name")
,super
调用了父类的参数"name"
,则能正常调用。
//父类==============================
public class Person {
public Person(String name) {
}
}
//子类==============================
public class Student extends Person{
public Student() {
super("name"); //不再报错
}
}
-
所以秦疆老师的经验谈:一旦重写了有参构造,先把无参构造加上。
-
小结:
super
调用父类的构造方法,必须在子类构造方法的第一行。super
只能出现在子类的方法或者构造器中。super
和this
不能同时调用构造器。super
对比this
:- 代表的对象不同:
this
代表的是本身调用者这个对象。super
代表的是父类对象的引用。
- 使用前提不同;
this
没有继承也可以使用。super
只能在继承条件下使用。
- 构造方法不同:
this();
本类的构造。super();
父类的构造。
- 代表的对象不同: