java super和this

103 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情

super(...)和this(...)

引入

class Person {
    private String name;
    private int age;
​
    public Person() {
        System.out.println("父类无参");
    }
​
    // getter/setter省略
}
​
class Student extends Person {
    private double score;
​
    public Student() {
        //super(); // 调用父类无参构造器,默认就存在,可以不写,必须再第一行
        System.out.println("子类无参");
    }
    
     public Student(double score) {
        //super();  // 调用父类无参构造器,默认就存在,可以不写,必须再第一行
        this.score = score;    
        System.out.println("子类有参");
     }
      // getter/setter省略
}
​
public class Demo07 {
    public static void main(String[] args) {
        // 调用子类有参数构造器
        Student s2 = new Student(99.9);
        System.out.println(s2.getScore()); // 99.9
        System.out.println(s2.getName()); // 输出 null
        System.out.println(s2.getAge()); // 输出 0
    }
}

我们发现,子类有参数构造器只是初始化了自己对象中的成员变量score,而父类中的成员变量name和age依然是没有数据的,怎么解决这个问题呢,我们可以借助与super(...)去调用父类构造器,以便初始化继承自父类对象的name和age.

super和this的用法格式

super和this完整的用法如下,其中this,super访问成员我们已经接触过了。

this.成员变量       --    本类的
super.成员变量      --    父类的
​
this.成员方法名()    --    本类的    
super.成员方法名()   --    父类的

接下来我们使用调用构造器格式:

super(...) -- 调用父类的构造器,根据参数匹配确认
this(...) -- 调用本类的其他构造器,根据参数匹配确认

super(....)用法演示

代码如下:

class Person {
    private String name ="凤姐";
    private int age = 20;
​
    public Person() {
        System.out.println("父类无参");
    }
    
    public Person(String name , int age){
        this.name = name ;
        this.age = age ;
    }
​
    // getter/setter省略
}
​
class Student extends Person {
    private double score = 100;
​
    public Student() {
        //super(); // 调用父类无参构造器,默认就存在,可以不写,必须再第一行
        System.out.println("子类无参");
    }
    
     public Student(String name , int age,double score) {
        super(name ,age);// 调用父类有参构造器Person(String name , int age)初始化name和age
        this.score = score;    
        System.out.println("子类有参");
     }
      // getter/setter省略
}
​
public class Demo07 {
    public static void main(String[] args) {
        // 调用子类有参数构造器
        Student s2 = new Student("张三"2099);
        System.out.println(s2.getScore()); // 99
        System.out.println(s2.getName()); // 输出 张三
        System.out.println(s2.getAge()); // 输出 20
    }
}

注意:

子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。

super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。

super(..)是根据参数去确定调用父类哪个构造器的。

super(...)案例图解

父类空间优先于子类对象产生

在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。代码体现在子类的构造器调用时,一定先调用父类的构造器。理解图解如下:

2.jpg

this(...)用法演示

this(...)

  • 默认是去找本类中的其他构造器,根据参数来确定具体调用哪一个构造器。
  • 为了借用其他构造器的功能。
package com.itheima._08this和super调用构造器;
class Student{
    private String name ;
    private int age ;
    private char sex ;
​
    public Student() {
  // 很弱,我的兄弟很牛逼啊,我可以调用其他构造器:Student(String name, int age, char sex)
        this("徐干",21,'男');
    }
​
    public Student(String name, int age, char sex) {
        this.name = name ;
        this.age = age   ;
        this.sex = sex   ;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
​
    public char getSex() {
        return sex;
    }
​
    public void setSex(char sex) {
        this.sex = sex;
    }
}
​
/**
 * this(...):
 *    默认是去找本类中的其他构造器,根据参数来确定具体调用哪一个构造器。
 *    为了借用其他构造器的功能。
 *
 */
public class ThisDemo01 {
    public static void main(String[] args) {
        Student xuGan = new Student();
        System.out.println(xuGan.getName()); // 输出:徐干
        System.out.println(xuGan.getAge());// 输出:21
        System.out.println(xuGan.getSex());// 输出: 男
    }
}
​
​

小结

  • 子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。
  • super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。
  • super(..)和this(...)是根据参数去确定调用父类哪个构造器的。
  • super(..)可以调用父类构造器初始化继承自父类的成员变量的数据。
  • this(..)可以调用本类中的其他构造器。